gpt4 book ai didi

reactjs - 对一组对象使用 useMemo/React.memo 以防止在编辑其中一个对象后重新渲染的最佳方法?

转载 作者:行者123 更新时间:2023-12-05 04:44:39 25 4
gpt4 key购买 nike

我正在努力解决我的 React 应用程序的性能问题。例如,我有一张卡片列表,您可以在 Facebook 上添加一个赞。一旦其中一个子项更新,所有列表都会重新呈现,所以在这里我尝试使用 useMemo 或 React.memo。我以为我可以将 React.memo 用于卡片组件,但没有成功。不确定我是否遗漏了一些重要的部分..

Parent.js

const Parent = () => {
const postLike= usePostLike()
const listData = useRecoilValue(getCardList)
// listData looks like this ->
//[{ id:1, name: "Rose", avararImg: "url", image: "url", bodyText: "text", liked: false, likedNum: 1, ...etc },
// { id:2, name: "Helena", avararImg: "url", image: "url", bodyText: "text", liked: false, likedNum: 1, ...etc },
// { id: 3, name: "Gutsy", avararImg: "url", image: "url", bodyText: "text", liked: false, likedNum: 1, ...etc }]

const memoizedListData = useMemo(() => {
return listData.map(data => {
return data
})
}, [listData])

return (
<Wrapper>
{memoizedListData.map(data => {
return (
<Child
key={data.id}
data={data}
postLike={postLike}
/>
)
})}
</Wrapper>
)
}
export default Parent

使用PostLike.js

export const usePressLike = () => {
const toggleIsSending = useSetRecoilState(isSendingLike)
const setList = useSetRecoilState(getCardList)

const asyncCurrentData = useRecoilCallback(
({ snapshot }) =>
async () => {
const data = await snapshot.getPromise(getCardList)
return data
}
)

const pressLike = useCallback(
async (id) => {
toggleIsSending(true)
const currentList = await asyncCurrentData()

...some api calls but ignore now
const response = await fetch(url, {
...blabla
})

if (currentList.length !== 0) {
const newList = currentList.map(list => {
if (id === list.id) {
return {
...list,
liked: true,
likedNum: list.likedNum + 1,
}
}
return list
})
setList(newList)
}
toggleIsSending(false)
}
},
[setList, sendYell]
)

return pressLike
}

Child.js


const Child = ({
postLike,
data
}) => {

const { id, name, avatarImg, image, bodyText, likedNum, liked } = data;

const onClickPostLike = useCallback(() => {
postLike(id)
})

return (
<Card>
// This is Material UI component
<CardHeader
avatar={<StyledAvatar src={avatarImg} />}
title={name}
subheader={<SomeImage />}
/>
<Image drc={image} />
<div>{bodyText}</div>
<LikeButton
onClickPostLike={onClickPostLike}
liked={liked}
likedNum={likedNum}
/>
</Card>
)
}


export default Child

LikeButton.js


const LikeButton = ({ onClickPostLike, like, likedNum }) => {
const isSending = useRecoilValue(isSendingLike)

return (
<Button
onClick={() => {
if (isSending) return;
onClickPostLike()
}}
>
{liked ? <ColoredLikeIcon /> : <UnColoredLikeIcon />}
<span> {likedNum} </span>
</Button>
)
}

export default LikeButton


这里的主要问题是,当其中一个列表更新时,使用备忘录的最佳方式是什么。记住父组件中的整个列表或每个子列表,或者在子组件中使用 React.memo ......(但想象一下,如果用户编辑它们,其他东西也会改变。例如文本,图像......)我总是看到父组件使用 React 开发工具突出显示。

最佳答案

use React.memo in a child component

您可以这样做并提供自定义比较器函数:


const Child = React.memo(
({
postLike,
data
}) => {...},
(prevProps, nextProps) => prevProps.data.liked === nextProps.data.liked
);

您当前对 useMemo 的使用没有任何作用。当您的组件有其他状态更新并且您需要计算昂贵的值时,您可以使用 useMemo 作为性能优化。假设您有一个显示列表的可折叠面板:


const [expand, setExpand] = useState(true);
const serverData = useData();
const transformedData = useMemo(() =>
transformData(serverData),
[serverData]);

return (...);

useMemo 使您不必在每次用户展开/折叠面板时都重新转换 serverData

请注意,如果您在效果中自行获取数据,这是一个人为的示例,但它确实适用于一些常见的库,例如 React Apollo。

关于reactjs - 对一组对象使用 useMemo/React.memo 以防止在编辑其中一个对象后重新渲染的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69317889/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com