我有一个组件,可以根据 array.filter 计算要传递的值。不好的是,即使数组的元素完全相同,也会因为每次 props 改变而导致新的渲染。
该组件依赖于从状态计算的值:
const [targets, setTargets] = useState<Target[]>([]);
这是当我不希望它重新渲染时重新渲染的元素。
<Map
settings={mediumKneeboardMapSettings}
targets={getTargets(kneeboardGroupSelected?.id)}
/>
这里是根据 groupId(如果传递)进行过滤的回调。
const getTargets = useCallback(
(groupId?: string) => {
if (!groupId) {
return targets;
}
const groupTargets = targets.filter(target => target.group === groupId);
return groupTargets;
},
[targets]
);
每次父渲染时,如果将 id
传递给 getTargets
,Map
组件就会重新渲染。如果传递了 undefined
,它不会重新渲染。这对我来说很有意义,因为如果传入一个 undefined
,它每次都会返回相同的数组的状态。
但是,如果我传递 id
映射会重新渲染,因为从 filter
方法创建了一个新数组,即使该元素的成员未更改(每个例如,传递相同的 2 个元素时)。该数组包含来自 targets
的原始元素。不好的事情是在每次渲染时,Map
组件都会将其视为传入新目标,即使参数没有更改。这很糟糕,因为 Map
中的效果会在目标更改时执行额外的工作。
如何计算数组的子集作为 props 传递,但如果元素相同,则不会触发对子项的更改?
我正在考虑 useMemo
之类的东西,我需要它来记住输入并保存输出,只要目标不改变(这会导致创建一个新函数),该函数就是纯函数由于回调)。
最佳答案
您可以使用useMemo()
来实现此目的
const groupTargets = useMemo(()=>targets.filter(target => target.group === groupId),[targets]);
它仅在目标发生变化时运行 或者在 Map.js 中你可以这样做
导出默认的 React.memo(Map)
这将浅比较 props 并在 props 改变时重新渲染
但是 Kent C Dodds
不鼓励使用 useCallback()
useMemo()
和 React.memo()
始终
,因为执行这些操作的成本高于重新渲染
的成本。引用https://kentcdodds.com/blog/usememo-and-usecallback
关于javascript - 传递由 array.filter 计算的值总是会导致 React 中的渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60707624/