-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[FilterValueSelector] Convert to functional component & add isMountedRef #2167
Conversation
aba40ea
to
4e43848
Compare
Sorry for the late notice on this since a lot of the work has been done, but the |
Specifically it was removed in #2047 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not ran the code but mostly seems reasonable.
I'm a bit concerned by the initial value of the hook - it seems like it would return false during the first render which seems wrong. Try running things not in strict mode (which causes a double render and see what happens?
* @returns MutableRefObject<boolean> The mounted status | ||
*/ | ||
export function useIsMountedRef(): MutableRefObject<boolean> { | ||
const isMounted = useRef(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be true so the hook returns true on a component's first render?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The component isn't mounted during the first render, however, it'll be mounted when the effects run? afaik
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/ and https://github.com/donavon/hook-flow it looks like you're right - I guess those "React updates DOM " phases are when something goes from not being mounted to is mounted so in that render before first mount a component is not mounted. I was thrown because the equivalent hook in quilt sets this to true, but it seems like that's a bug on their side: https://github.com/Shopify/quilt/blob/master/packages/react-hooks/src/hooks/mounted-ref.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had mentioned this to @michenly and it sounds like this is the intention. From slack: I think you should think of this line more like a constructor of the class and the value will remain true till componentWillUnmount... it is not equal to componentDidMount... I wonder if it should be renamed to useUnMountedRef
,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically where we are using useMountedRef
from quilt are for checking if something had become un-mounted, so even thought the implementation is not exactly accurate it had been working so far.
I would like to fix it as a bug, but wonder if we would run into any situation where going from false -> true - > false will introduce a flash in UI. So this might need to be a breaking change with a more clear new name to avoid confusion.
@tmlayton No worries 😄 It was a fairly fast refactor and we still might as well 🚢 this incase we can remove |
4e43848
to
0c5eedf
Compare
The missing |
[onChange, onFilterKeyChange, value], | ||
); | ||
|
||
if (showOperatorOptions && operatorText!.length !== 0 && !isMounted) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we're checking isMounted
which is the ref object - I assume it should be isMounted.current
- as it stands this will always be false as we're evaluating !{ current: 'someValue'}
.
We only ever check isMounted in the render function. If this is being checked in a render function then the mount state is false if it is the first render, or true in every other case. (Compare to being called in a onClick or some other handler callback where the mounted state may change between the handler being called and when we check the current value of the ref)
If I'm interpreting that right then it means that this call to handleOperatorOptionChange only happens after the first render. In that case can we use the existing useIsAfterInitialMount
hook instead of creating a new custom hook?
We'd need a useMountedRef hook if we wanted to check the mounted state at any other point where a component may be unmounted - notably in a callback that might wait for a bit of time before being executed (either because of a setInterval or because it was awaiting on some async thing like a network call) and during that time the component got unmounted, but in this case when we only check the value in the render function useIsAfterInitialMount would do the job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤦♂ I should create a linting rule for this. I'm guessing this'll come up every now and then
This block will execute during the first render, not after. The different between useIsMountedRef
& useIsAfterInitialMount
is that useIsAfterInitialMount
is going to cause a re-render and useIsMountedRef
will not.
* @returns MutableRefObject<boolean> The mounted status | ||
*/ | ||
export function useIsMountedRef(): MutableRefObject<boolean> { | ||
const isMounted = useRef(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/ and https://github.com/donavon/hook-flow it looks like you're right - I guess those "React updates DOM " phases are when something goes from not being mounted to is mounted so in that render before first mount a component is not mounted. I was thrown because the equivalent hook in quilt sets this to true, but it seems like that's a bug on their side: https://github.com/Shopify/quilt/blob/master/packages/react-hooks/src/hooks/mounted-ref.ts
0c5eedf
to
6f71ee5
Compare
💦 Potential splash zone of changes introduced to
DetailsAll files potentially affected (total: 4)
📄
|
WHY are these changes introduced?
Part of #1995
WHAT is this pull request doing?
How to 🎩
Playground with filters below
Copy-paste this code in
playground/Playground.tsx
:🎩 checklist
README.md
with documentation changes