I can explain this.
- Memo does light comprasion, no deeply comprasion.
- When you pass string in children, then memo will be work with children.
- If you pass some elements or components, props.childrens will be contain array with refs on passed elements. Each render will receive a new array. An array may have the same content, but the reference to the array will be different. These are different arrays, memo doesn't do deep comparisons. It does not compare the contents of arrays, objects, but only references to them.
Based on the above, why doesn't this work on your example. You are passing the "h1" element as children. In your child component comes an array with one "h1" element. And for each render of the parent, a new array will come. Yes, it will be an array with the same content, but it is not the same array, not the same reference. Memo does not do deep checks.
Below two examples, with string and elements.
// if you pass string as children, memo will be work
const MemoizedChildComponent = memo(({children}) => {
console.log('render', children) // only one time render, children: "string"
return <div>children</div>
})
const App = () => {
const [count, setCount] = useState(1)
const handleCountIncrement = () => {
setCount(count + 1)
}
return <div>
<button onClick={handleCountIncrement}>increase</button>
<MemoizedChildComponent>string</MemoizedChildComponent> // pass simple string
</div>
}
But what if you don’t want to abandon the elements and want to memoize them?
I suggest use useMemo hook for memoize passed children.
I won't say that's good. But it will help if your goal is to memoize children. You can't solve this problem with memo. There is no deep comparison, so there is a problem with memo and children. Don't forget to specify dependencies in useMemo, there are none in the example, so the dependencies array is empty.
const MemoizedChildComponent = memo(({children}) => {
console.log('render', children) // only one time render, because it children memoized in parent component inside useMemo hook. children: [object, object, object]
return <div>children</div>
})
const App = () => {
const [count, setCount] = useState(1)
const handleCountIncrement = () => {
setCount(count + 1)
}
const memoizedChildren = useMemo(() => [
<p key="1">asd</p>,
<p key="2">asd</p>,
<p key="3">asd</p>
], [])
return <div>
<button onClick={handleCountIncrement}>increase</button>
<MemoizedChildComponent>{memoizedChildren}</MemoizedChildComponent>
</div>
}