I have the following structure in my React code:
const Parent: React.FC<ParentProps> = (props) => {
const [value1, setValue1] = useState<any>(null);
return (
<div>
<SomeContextProvider
contextElem1={value1}
contextElem2={value2}
>
...some code here
<Child
prop1={value3}
prop2={value4}
/>
</SomeContextProvider>
</div>
);
}
export default Parent;
const Child: React.FC<ChildProps> = ({ prop1, prop2 }) => {
return (
<div>
{prop1} {prop2}
</div>
);
}
const propsAreEqual = (prevProps: ChildProps, nextProps: ChildProps) => {
return true;
}
export default React.memo(Child, propsAreEqual);
As you notice:
Child
component does not consume SomeContextChild
component is only wrapped with SomeContextProvider (does this mean that the child is consuming the context?)Here is the scenario:
Parent
is re-rendered, the Child
is also re-rendered even if the Child
does not consume the SomeContext
and propsAreEqual
returns true
.Child
to outside scope, React.memo
works as expected and prevents re-rendering of Child
when Parent
is re-rendered.How come Child
is re-rendered while it is not consuming the context? Isn't React.memo
supposed to prevent re-renders? What do I miss about these concepts?
I think you are mistaken. I copied your code into a CodeSandbox and modified it so it actually builds. The child does not render whenever the parent re-renders, because you've wrapped it in React.memo()
. (If I remove the memo()
then the child does re-render.)
https://codesandbox.io/s/misty-feather-tl3p6?file=/src/App.js
If your code is triggering re-renders, it might be because of your specific implementation of the propsAreEqual function or the values you are passing for value3
or value4
.