Skip to content

Conversation

chad1008
Copy link
Contributor

What?

Updates the ToolsPanel component to satisfy the exhaustive-deps eslint rule

Why?

Part of the effort in #41166 to apply exhuastive-deps to the Components package

How?

In tools-panel/hook.ts, we can safely remove generateMenuItems from dep arrays. React can't tell if an outer scope value like this changes, so it would never trigger a re-render, nor would it cause the effect to actually fire.

We can also safely remove isResetting.current from the dependency arrays. Including a ref.current value in a dependency array isn't recommended in general.

In the relevant useCallback, the value is updated, but never actually read... so even if it had changed, that wouldn't impact the callback's behavior.

In the relevant useMemo, the value is read, so changes matter, but including the dependency in the array gives a false sense of security. If that were the only dep to change on a given render, React wouldn't notice, and the memoized value wouldn't update. If we really want the isResetting value to trigger a re-render to update this memo it should go into state, or a reducer. Because the component has functioned properly as it is now thus far, I think we should hold off on introducing new state (which will be sure to trigger additional renders and potentially other behavior changes) and simply remove the dependency. cc @aaronrobertshaw in case you have any insights, as you did some work with the isResetting value here most recently.

Finally, in tools-panel-item/hook.ts, a number of missing dependencies were added. In each case the added dep(s) are values being destructured from one of two contexts, so they'd cause their hooks to fire on every render. However, all of these hooks already have dependencies that are being destructured in this way, or derived from similar variables... so these new dependencies shouldn't change the existing behavior of anything. (Please feel free to correct me if my logic doesn't sound right here!)

Testing Instructions

  1. From your local Gutenberg directory, run npx eslint --rule 'react-hooks/exhaustive-deps: warn' packages/components/src/tools-panel
  2. Confirm that the linter returns no errors
  3. Confirm unit tests still pass
  4. Run Storybook locally, confirm the components stories and/or docs still work as expected

@chad1008 chad1008 added [Type] Code Quality Issues or PRs that relate to code quality [Package] Components /packages/components [Feature] Component System WordPress component system labels Oct 17, 2022
@chad1008 chad1008 requested a review from ajitbohra as a code owner October 17, 2022 14:07
@chad1008 chad1008 self-assigned this Oct 17, 2022
@chad1008 chad1008 force-pushed the refactor/ToolsPanel-exhaustive-deps branch from e95a41c to 9d0faaf Compare October 17, 2022 14:12
Copy link
Contributor

@aaronrobertshaw aaronrobertshaw left a comment

Choose a reason for hiding this comment

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

Nice work @chad1008, appreciate the detailed notes and context 👍

This tests well for me:

✅ No linting errors with exhaustive-deps
✅ Unit tests are passing
✅ Storybook examples continue to function
✅ No differences in behaviour in Block and Site Editors

If we really want the isResetting value to trigger a re-render to update this memo it should go into state

I believe the isResetting value passed via context to the tools panel items was so that individual items could prevent calling their onSelect/onDeselect callbacks when the overall panel was executing a "reset all". When the "reset all" is being done, the menu items state is updated which would force the useMemo update. So as you noted, we should be safe to simply remove the dependency.

@chad1008 chad1008 force-pushed the refactor/ToolsPanel-exhaustive-deps branch from 9d0faaf to 59ddeb2 Compare October 18, 2022 15:06
@chad1008
Copy link
Contributor Author

Thanks @aaronrobertshaw! Much appreciated!

@ciampo how are you feeling about this one? I particularly wanted to double check your thoughts on the added dependencies in tools-panel-item/hook.ts:

...all of these hooks already have dependencies that are being destructured in this way, or derived from similar variables... so these new dependencies shouldn't change the existing behavior of anything. (Please feel free to correct me if my logic doesn't sound right here!

If that sounds logical to you, I'll wait for the checks to pass and get this merged 🙂

@ciampo
Copy link
Contributor

ciampo commented Oct 19, 2022

Changes look good to me — although I'm not sure I understand this part of your reasoning:

In each case the added dep(s) are values being destructured from one of two contexts, so they'd cause their hooks to fire on every render.

I may be wrong, but I don't think that destructuring values from those contexts automatically means that the hooks will run on every render.


Apart from that, I also gave a quick at how the component behaves in the editor and I couldn't spot any unexpected behavior. Plus, this component was mostly written by @aaronrobertshaw (including lots of unit tests!), and therefore seeing that he already approved this PR is great 🚀

@chad1008 chad1008 merged commit 15ae7e3 into trunk Oct 19, 2022
@chad1008 chad1008 deleted the refactor/ToolsPanel-exhaustive-deps branch October 19, 2022 12:17
@github-actions github-actions bot added this to the Gutenberg 14.4 milestone Oct 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Component System WordPress component system [Package] Components /packages/components [Type] Code Quality Issues or PRs that relate to code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants