Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve findDOMNode deprecation by merging ScrollBlock and ScrollCaptor into ScrollManager #4330

Merged
merged 8 commits into from
Jan 22, 2021

Conversation

Rall3n
Copy link
Collaborator

@Rall3n Rall3n commented Dec 13, 2020

This is an alternative PR to #4102 to resolve the findDOMNode deprection of #4094.

As #4102 tried to solve the issue through adding the reference as a prop, this PR aims to provide a solution by merging the components ScrollBlock and ScrollCaptor into a single ScrollManager component. This component will have its own reference to the needed DOM element (instead of one through props), which resulted in the children prop being a function.

In its conception both ScrollBlock and ScrollCaptor were planned to have their own references with children also being a function. But to minimize possible performance issues they resulted in being merged into the ScrollManager component.

@changeset-bot
Copy link

changeset-bot bot commented Dec 13, 2020

⚠️ No Changeset found

Latest commit: 28ee545

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@codesandbox-ci
Copy link

codesandbox-ci bot commented Dec 13, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 28ee545:

Sandbox Source
react-codesandboxer-example Configuration

@Rall3n Rall3n force-pushed the findDOMNode-ScrollManager branch from d179d6c to 7892455 Compare December 13, 2020 05:10
Copy link
Collaborator

@Methuselah96 Methuselah96 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I'm assuming we can get rid of the ScrollBlock and ScrollCaptor components in this PR as well?


setTargetRef = (instance: HTMLElement | null) => {
this.targetRef.current = instance;
this.setState({ enableLock: !!instance });
Copy link
Collaborator

@Methuselah96 Methuselah96 Dec 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the intent is to trigger a re-render, can we store the element in state, similar to what ScrollBlock does? That way we can avoid re-rendering if the element is the same as well as avoid removing and then reattaching the listeners to the same element. I know you've said you're against storing an element in state, I'd be curious to know why.

Another option would be to make ScrollLock not a React component anymore since all it does is attach event listeners to the element and it doesn't actually render anything. It could just expose two methods, one to add listeners and one to remove them and we could call them in the appropriate lifecycle methods in ScrollManager. If I understand the situation correctly, I think this would remove the need to trigger a re-render for ScrollLock by setting state, which I would be a fan of.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the intent is to trigger a re-render, can we store the element in state, similar to what ScrollBlock does?

I know you've said you're against storing an element in state, I'd be curious to know why.

I learned and made it my ideology, that state is explicitly for data, while references to DOM elements and possibly React components should be kept in refs. That is why I`m against it. Period.

Another option would be to make ScrollLock not a React component anymore since all it does is attach event listeners to the element and it doesn't actually render anything.

The React mindset is all about components. And I think either would not be an improvement over the other.

Copy link
Collaborator

@Methuselah96 Methuselah96 Dec 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding putting the DOM element in state, that's fine, I would prefer not putting DOM elements in state as well (although I think that's sometimes the best solution available, just not in this case).

While the React mindset is all about components, that doesn't mean literally every piece of logic has to live in a component. There's already precedent in react-select to take logic that makes most sense in a componentDidMount, etc. and abstracting it into a function based on utils.js.

I would also argue that the mindset of React is also against taking DOM elements received from refs and passing them down to child components through props, because it makes it difficult to make sure that those elements are properly received without forcing what should be an unnecessary re-render on the parent component. The reason why componentDidMount, etc. exist are to perform actions on DOM elements that are received via refs after the render has taken place, but that breaks down as soon as you start passing elements received from refs as props to other components.

Copy link
Collaborator

@Methuselah96 Methuselah96 Dec 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, components that always return null in the render method (like ScrollLock) don't really fit into the React mindset either.

Copy link
Collaborator Author

@Rall3n Rall3n Dec 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Back to topic: I don't think it's worth the effort to rewrite ScrollLock (for this PR). Maybe add it to the backlog?

Copy link
Collaborator

@Methuselah96 Methuselah96 Dec 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds fine, I'll make a follow-up PR to avoid the re-render in ScrollManager and hopefully we can get them merged in back-to-back for 4.0, or if there is a problem with the follow-up PR, we can just wait to merge it in order to get this released ASAP.


Would we have to use the same pattern of having a (ref) => { } child function if it were a wrapping component? That seems like a necessary pattern in these situations, but I personally think it adds unnecessary complexity when you're doing it more than once for the same DOM element. I understand the intention to abstract the functionality into a reusable component, but I think there's a simpler way to achieve this behavior that follows good coding practices and is still in the React mindset (imo).

Yeah, using a library sounds good too. For that specific library I'm not sure I understand how it works if the child is a component and not a function because it seems like it's just getting a ref to the child component and not a ref to the DOM element (based on this line)? Although to be fair I only looked at it very quickly, so I could easily be missing something.

@Methuselah96 Methuselah96 added this to the 4.0 milestone Dec 15, 2020
@ebonow ebonow added the menu-bug Addresses menu positioning, scrolling, or general interactions label Jan 16, 2021
@Rall3n Rall3n force-pushed the findDOMNode-ScrollManager branch from c6040e3 to 12a2c7a Compare January 17, 2021 16:49
@JedWatson JedWatson merged commit 7c54eb1 into JedWatson:master Jan 22, 2021
@Rall3n Rall3n deleted the findDOMNode-ScrollManager branch February 2, 2022 08:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
menu-bug Addresses menu positioning, scrolling, or general interactions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants