如何将 React.memo 与包含 children 的组件一起使用
how to use React.memo with a Component contains children
我有两个组件,我用 React.memo
:
包装了 Parent
Child
const Child = ()=> <div>I'm Child</div>
export default Child
Parent
const Parent = (props)=> <div>{props.children}</div>
export default React.memo(Parent)
在应用程序中使用:
const App = () => {
const [count, setCount] = useState(0)
return(
<div>
<button onClick={()=>setCount(count+1)}></button>
<Parent>
<Child></Child>
</Parent>
</div>
)
}
点击按钮,结果:
Parent 组件将重新呈现,因此备忘录无法正常工作,因为它 children 是一个函数组件
那么,如何防止重新渲染?
我知道用useMemo解决的方法,但是丑陋不友好,有没有更好的办法?
const App = () => {
const [count, setCount] = useState(0)
const children = useMemo(()=><Child></Child>,[])
return(
<div>
<button onClick={()=>setCount(count+1)}></button>
<Parent>
{children}
</Parent>
</div>
)
}
将您的 <Child />
换成 React.memo
:
const Child = ()=> {
console.log('render') // fires only once - on initial render
return <div>I'm Child</div>
}
const MChild = React.memo(Child);
const Parent = (props)=> <div>{props.children}</div>
const MParent = React.memo(Parent)
const App = () => {
const [count, setCount] = useState(0);
return(
<div>
<button onClick={()=>setCount(count+1)}>increment {count}</button>
<MParent>
<MChild></MChild>
</MParent>
</div>
)
}
render(<App />, document.getElementById('root'));
const children = useMemo(()=><Child></Child>,[])
是最简单的方法。使用 memo(Child)
不会起作用,因为 jsx 实际上 returns 每当您调用 <Child />
时都是一个新对象。 React.memo
默认情况下只使用简单的浅比较,所以真的没有其他直接的方法来解决它。您可以创建自己的最终支持儿童的功能并将其传递给 React.memo(MyComp, myChildrenAwareEqual)
.
将 <Parent><Child/></Parent>
移动到一个单独的组件中,并记住 那个 组件:
const Family = memo(() => <Parent><Child/></Parent>);
const App = () => {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count => count + 1)}>{count}</button>
<Family />
</>
)
}
const Memo = React.memo(({ children, value }) => {
return children
}, (prev, next) => prev.value === next.value)
然后使用它
function Title() {
const [count, setCount] = useState(0)
const onClick = () => {
setCount(c => c + 1)
}
const a = ''
return (
<>
<div onClick={onClick}>{count}</div>
<Memo value={a}>
<Child>
<Nothing2 a={a} />
</Child>
</Memo>
</>
)
}
当 a
发生变化时,Child 渲染,否则它会使用之前的渲染退出。
我在我的博客中概述了它背后的原理,https://javascript.plainenglish.io/can-usememo-skip-a-child-render-94e61f5ad981
我有两个组件,我用 React.memo
:
Child
const Child = ()=> <div>I'm Child</div>
export default Child
Parent
const Parent = (props)=> <div>{props.children}</div>
export default React.memo(Parent)
在应用程序中使用:
const App = () => {
const [count, setCount] = useState(0)
return(
<div>
<button onClick={()=>setCount(count+1)}></button>
<Parent>
<Child></Child>
</Parent>
</div>
)
}
点击按钮,结果:
Parent 组件将重新呈现,因此备忘录无法正常工作,因为它 children 是一个函数组件
那么,如何防止重新渲染?
我知道用useMemo解决的方法,但是丑陋不友好,有没有更好的办法?
const App = () => {
const [count, setCount] = useState(0)
const children = useMemo(()=><Child></Child>,[])
return(
<div>
<button onClick={()=>setCount(count+1)}></button>
<Parent>
{children}
</Parent>
</div>
)
}
将您的 <Child />
换成 React.memo
:
const Child = ()=> {
console.log('render') // fires only once - on initial render
return <div>I'm Child</div>
}
const MChild = React.memo(Child);
const Parent = (props)=> <div>{props.children}</div>
const MParent = React.memo(Parent)
const App = () => {
const [count, setCount] = useState(0);
return(
<div>
<button onClick={()=>setCount(count+1)}>increment {count}</button>
<MParent>
<MChild></MChild>
</MParent>
</div>
)
}
render(<App />, document.getElementById('root'));
const children = useMemo(()=><Child></Child>,[])
是最简单的方法。使用 memo(Child)
不会起作用,因为 jsx 实际上 returns 每当您调用 <Child />
时都是一个新对象。 React.memo
默认情况下只使用简单的浅比较,所以真的没有其他直接的方法来解决它。您可以创建自己的最终支持儿童的功能并将其传递给 React.memo(MyComp, myChildrenAwareEqual)
.
将 <Parent><Child/></Parent>
移动到一个单独的组件中,并记住 那个 组件:
const Family = memo(() => <Parent><Child/></Parent>);
const App = () => {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count => count + 1)}>{count}</button>
<Family />
</>
)
}
const Memo = React.memo(({ children, value }) => {
return children
}, (prev, next) => prev.value === next.value)
然后使用它
function Title() {
const [count, setCount] = useState(0)
const onClick = () => {
setCount(c => c + 1)
}
const a = ''
return (
<>
<div onClick={onClick}>{count}</div>
<Memo value={a}>
<Child>
<Nothing2 a={a} />
</Child>
</Memo>
</>
)
}
当 a
发生变化时,Child 渲染,否则它会使用之前的渲染退出。
我在我的博客中概述了它背后的原理,https://javascript.plainenglish.io/can-usememo-skip-a-child-render-94e61f5ad981