In the profiling result the component (Table
) uses React.memo
and it is shown that did not re-render
but underneath there is shown the same Table
component and in Why did this render is mentioned that parent re-rendered
The Table
uses memo this way and the querystring
stays the same.
function areEqal(prevTable, nextTable) {
return prevTable.queryString === nextTable.queryString;
}
const MemoTable = memo(Table, areEqal);
...
<MemoTable queryString={queryString} />
The question is, why the Table
is shown twice (once not re-rendered, then yes) and why it re-renders when memoized to re-render just when querystring
changes.
memo
can only prevent renders related to props. Rendering may still happen if a context value that you're subscribed to changes. As discussed in the comments, you are apparently using a couple of contexts, and those are what's causing the render.
While deleting the useContext
s appears to have worked for your case, the fact that you weren't expecting this rerender may indidate that the DataContext.provider has a common mistake in which you're changing the context value on every render. If you're providing an object, you need to make sure to only create a new object when the properties of the object have actually changed. So for example, if your current code is this:
const Example = ({ children }) => {
const [userPreferences, setUserPreferences] = useState('something');
return (
<DataContext.Provider value={{ userPreferences, setUserPreferences }}>
{children}
</DataContext.Provider>
);
}
... then you should memoize the value like this:
const Example = ({ children }) => {
const [userPreferences, setUserPreferences] = useState('something');
const value = useMemo(() => {
return { userPreferences, setUserPreferences }
}, [userPreferences]);
return (
<DataContext.Provider value={value}>
{children}
</DataContext.Provider>
);
}
As for the two copies of Table
in the dev tools, the first is the memoized component MemoTable. MemoTable then renders an unmemoized Table inside of it, and that's the second one. "Table (memo)" is the default name that memo
gives to the component it returns. If you'd like to change that name so it shows up differently in the dev tools, you can:
const MemoTable = memo(Table, areEqal);
MemoTable.displayName = "Hello world";