constMovingComponent = ({ children }) => { ... return ( <div...// callbackssameasbefore > // children as render function with some data // data doesn't depend on the changed state! {children({ data: 'something' })} </div> ); };
constSomeOutsideComponent = () => { return ( <MovingComponent> // ChildComponent re-renders when state in MovingComponent changes! // even if it doesn't use the data that is passed from it {() => <ChildComponent />} </MovingComponent> ) }
React.memo behavior
memo parent
// wrapping MovingComponent in memo to prevent it from re-rendering constMovingComponentMemo = React.memo(MovingComponent);
constSomeOutsideComponent = () => { // trigger re-renders here with state const [state, setState] = useState();
return ( <MovingComponentMemo> <!-- ChildComponent will still re-render when SomeOutsideComponent re-renders --> <ChildComponent /> </MovingComponentMemo> ) }
memo child
// wrapping ChildComponent in memo to prevent it from re-rendering constChildComponentMemo = React.memo(ChildComponent);
constSomeOutsideComponent = () => { // trigger re-renders here with state const [state, setState] = useState();
return ( <MovingComponent> <!-- ChildComponent won't re-render, even if the parent is not memoized --> <ChildComponentMemo /> </MovingComponent> ) }
useCallback hook behavior
constSomeOutsideComponent = () => { // trigger re-renders here with state const [state, setState] = useState();
// trying to prevent ChildComponent from re-rendering by memoising render function. Won't work! const child = useCallback(() =><ChildComponent />, []);
return ( <MovingComponent> <!-- Memoized render function. Didn't help with re-renders though --> {child} </MovingComponent> ) }
Why?
什么是react 的child?
constParent = ({ children }) => { return<>{children}</>; };
constParent = () => { // child definition object will be re-created. // so Child component will be re-rendered when Parent re-renders const child = <Child />;
constMovingComponent = ({ children }) => { // this will trigger re-render const [state, setState] = useState(); return ( <div // ... style={{left:state.x, top:state.y }} > <!-- those won't re-render because of the state change --> {children} </div> ); };
constMovingComponent = ({ children }) => { // this will trigger re-render const [state, setState] = useState(); return ( <div ///... > <!-- those will re-render because of the state change --> {children()} </div> ); };
constSomeOutsideComponent = () => { // trigger re-renders here with state const [state, setState] = useState();
// this memoization doesn't prevent re-renders of ChildComponent const child = useCallback(() =><ChildComponent />, []);
return<MovingComponent>{child}</MovingComponent>; }; // same as constSomeOutsideComponent = () => { // trigger re-renders here with state const [state, setState] = useState();
// this memoization doesn't prevent re-renders of ChildComponent const child = useCallback(() =><ChildComponent />, []);