There is a tree-like structure which should be expanded to make all checked children visible.
Here is the code:
const { data } = useGetData(); // react-query hook that gets data from an endpoint
Next, there is a function that returns an array with a node's parents nodes:
const getAllParents = (key: string, parentNodes: string[]) => {
Object.keys(data).forEach((itemKey: string) => {
if (
data[itemKey]?.hasChildren &&
data[itemKey].children?.filter((child: string) => child === key).length
) {
parentNodes.push(itemKey);
getAllParents(itemKey, parentNodes);
}
});
return parentNodes;
};
And here is the useEffect, that should run once after the tree is loaded:
useEffect(() => {
let allParents: string[] = [];
let uniqueParents: string[] = [];
selectedItems.forEach((item) => {
const itemParents: string[] = getAllParents(item, []);
allParents = [...allParents, ...itemParents];
uniqueParents = [...new Set(allParents)];
});
setExpandedItems(uniqueParents);
}, [getAllParents, selectedItems, uniqueParents]);
The problem is that this useEffect run continuously. There is a way to stop it from doing that, by removing getAllParents
from dependency array.
But doing this shows the warning: React Hook useEffect has a missing dependency: 'getAllParents'. Either include it or remove the dependency array.
Anyway, it still doesn't work fine, it should only run once when the tree is loaded. Any ideas how to do that?
UPDATE AFTER ADDING USECALLBACK:
I have wrapped getAllParents
inside a useCallback:
const getAllParents = useCallback((key: string, parentNodes: string[]) => { ... }, [data]);
For useEffect:
if the dependency array is empty (
[]
): it doesn't run at all, the tree is not expanded[getAllParents, selectedItems]
: it will run forever again[ selectedItems]
: it seems to work fine but with the same warning about a missing dependency.
CodePudding user response:
If the getAllParents
is defined inside the React component, useEffect
will treat it as a new function with each render (comparing by reference).
Try wrapping it with useCallback
to avoid creating a new function for every render
CodePudding user response:
you can try to wrap the getAllParents
function with React.useCallback
hook