useCallback 依赖数组违背了更新数组时防止重新渲染的目的
以下 React 应用程序显示水果列表。每个 Fruit
都有一个“添加到收藏夹”按钮,该按钮使用 addFav
回调将所述水果添加到父项中的收藏夹列表中。传入 handleAddFav
回调会导致不必要的重新渲染,因此我将其包装在 useCallback
中,并将 Fruit
包装在 memo
中。
然而,useCallback
要求在其依赖项数组中包含 favs
,这会导致 handleAddFav
在每次调用时都要重新计算。这违背了使用 useCallback 来停止重新渲染的目的,因为现在每次添加收藏夹时,每个 Fruit
都会重新渲染。我该如何解决这个问题?
import { useState, memo, useCallback } from "react";
import "./styles.css";
const Fruit = memo(({title, id, addFav}) => {
console.log(title, 'rendered')
return (
<div>
<div>{title}</div>
<button onClick={() => addFav(title, id)}>add fav</button>
</div>
)
})
export default function App() {
const [favs, setFavs] = useState([])
const data = [{title: 'apple', id: '1'}, {title:'orange', id:'2'}
, {title:'banana', id:'3'}]
const handleAddFav = useCallback((title, id) => {
setFavs([...favs, {title, id}])
}, [favs])
return (
<div className="App">
<h1>Testing useCallback that sets an array</h1>
<h2>Favorites</h2>
<button onClick={() => setFavs([])}>clear</button>
{
favs.map(({title, id}, i) => <span key={id + i}>{title}</span>)
}
{
data.map(({title, id }) => (
<Fruit key={id} title={title} id={id} addFav={handleAddFav}/>
))
}
</div>
);
}
The following React app displays a list of fruits. Each Fruit
has a "add to fav" button which uses a addFav
callback to add said fruit to a list of favourites in the parent. Passing in the handleAddFav
callback causes unnecessary re-renders, so I wrapped it in a useCallback
and Fruit
in memo
.
However the useCallback
demands to have favs
in its dependency array which causes the handleAddFav
to be re-computed every time its called. This defeats the purpose of using useCallback to stop re-renders because now each Fruit
re-renders every time you add a favourite. How can I solve this?
import { useState, memo, useCallback } from "react";
import "./styles.css";
const Fruit = memo(({title, id, addFav}) => {
console.log(title, 'rendered')
return (
<div>
<div>{title}</div>
<button onClick={() => addFav(title, id)}>add fav</button>
</div>
)
})
export default function App() {
const [favs, setFavs] = useState([])
const data = [{title: 'apple', id: '1'}, {title:'orange', id:'2'}
, {title:'banana', id:'3'}]
const handleAddFav = useCallback((title, id) => {
setFavs([...favs, {title, id}])
}, [favs])
return (
<div className="App">
<h1>Testing useCallback that sets an array</h1>
<h2>Favorites</h2>
<button onClick={() => setFavs([])}>clear</button>
{
favs.map(({title, id}, i) => <span key={id + i}>{title}</span>)
}
{
data.map(({title, id }) => (
<Fruit key={id} title={title} id={id} addFav={handleAddFav}/>
))
}
</div>
);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一种方法是使用
setFavs
的函数版本,因此它不依赖于外部变量。对于更一般的情况 - 即使您确实有一个必须重新计算的值,使用
useCallback
仍然可以减少 其他 值的情况的重新渲染组件发生变化,但计算值没有变化。例如,如果
cb
被传递下来,即使它依赖于num
,useCallback
仍然会在只有 < code>toggled 发生更改,而num
保持不变。One way is to use the function version of
setFavs
instead, so it doesn't depend on an outer variable.For the more general situation - even if you did have a value that had to be re-computed, using
useCallback
could still reduce re-renders for the cases in which other values in the component change, but not the computed value. For exampleIf
cb
is passed down, even though it depends onnum
,useCallback
will still prevent child re-renders in the case where onlytoggled
gets changed, andnum
stays the same.