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

[data grid] Reduce the use of useGridSelector in root-level hooks #16001

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

lauri865
Copy link
Contributor

@lauri865 lauri865 commented Dec 26, 2024

As discussed in #15986 (comment)

The use of useGridSelector should be avoided whenever possible in root level (feature) hooks, as it sends the whole grid root and all sibling hooks to re-evaluate on every time selecto state changes. There's many instances, where useGridSelector values are passed to useCallback, which re-creates callback functions and event listeners on state changes. If the callbacks are indeed callbacks, the state they access is identical to just evaluating the selector within the callback itself.

This instance is a bit more difficult to refactor for the time being, but will be very easy once #15666 gets merged as it'll be refactored as a pure selector then:

const initialCurrentPageRows = useGridVisibleRows(apiRef, props).rows;

The only instances where useGridSelector is valid truly valid and necessary are useGridDimensions and useGridRowsMeta as they need to perform calculations in response to many different parts of the state. If those were to be optimised further, they could be moved to a separate component, so they wouldn't affect all the other hooks any time the state they depend on changes.

Two other instances that were difficult to refactor currently:

const groupsToAutoFetch = useGridSelector(apiRef, gridRowGroupsToFetchSelector);

function useColumnVirtualizationDisabled(apiRef: React.MutableRefObject<GridPrivateApiCommunity>) {

But they are pretty minor.

However, if we could get rid of them completely, I think it would make for a good convention not to allow selector hooks in root-level feature hooks. Makes it easier to write more isolated features, and safer to introduce experimental features. Alternative is:
#15986 (comment)

@mui-bot
Copy link

mui-bot commented Dec 26, 2024

Deploy preview: https://deploy-preview-16001--material-ui-x.netlify.app/

Generated by 🚫 dangerJS against 68286c2

@lauri865 lauri865 force-pushed the reduce-use-grid-selector-use-in-root branch from 136ecee to 3ac7422 Compare December 26, 2024 10:26
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Dec 26, 2024
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Dec 26, 2024
@lauri865 lauri865 force-pushed the reduce-use-grid-selector-use-in-root branch from 0e5d227 to 3ac7422 Compare December 26, 2024 10:28
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Dec 26, 2024
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Signed-off-by: Lauri <lauri.lehtmaa@gmail.com>
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Dec 26, 2024
@lauri865
Copy link
Contributor Author

Out of curiosity, I moved useGridDimensions and useGridRowsMeta into a separate component (locally, haven't pushed these changes, but happy to do so if there's interest).

It broke a few tests, most notably anything related to tree data. Revealing that `useGridVisibleRows' is a problematic hook – it currently only works due to side-effects of other state updating it seems.

Again, it will be an easy fix once #15666 gets merged (fyi @romgrk).

But this confirms my hunch that avoiding useGridSelector in root level feature hooks is probably a good convention to have – not only for performance considerations, but also forces one to write more isolated code and avoids cases of things working due to side-effects.

@lauri865
Copy link
Contributor Author

I'm not sure if this function is legacy, but I cannot see any case where the useColumnVirtualizationDisabled function could hit anything but this code path after invoking apiRef.current.unstable_setColumnVirtualization(false):
https://github.com/mui/mui-x/blob/61d8511407190a7f1b7a4f4a672ffe3ee3b33342/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx#L149C7-L151C8

So, I simplified it, and got rid of the last root-level useGridSelector. Technically any async function that is awaited could do the trick, but for semantics and to avoid future breaking, it's better to check the selector anyways. Correct me if I'm wrong, but tested with virtualized columns and everything worked with the new implementation.

@zannager zannager added the component: data grid This is the name of the generic UI component, not the React module! label Dec 30, 2024
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Dec 30, 2024
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@lauri865
Copy link
Contributor Author

@MBilalShafi, out of curiosity, why did you change the below from an event (was previously triggered by rowsSet I believe) to a useEffect? Just trying to understand the limits of my suggestion.

React.useEffect(() => {
if (
groupsToAutoFetch &&
groupsToAutoFetch.length &&
scheduledGroups.current < groupsToAutoFetch.length
) {
const groupsToSchedule = groupsToAutoFetch.slice(scheduledGroups.current);
nestedDataManager.queue(groupsToSchedule);
scheduledGroups.current = groupsToAutoFetch.length;
}
}, [apiRef, nestedDataManager, groupsToAutoFetch]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: data grid This is the name of the generic UI component, not the React module! PR: out-of-date The pull request has merge conflicts and can't be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants