我是React钩子的新手,正在尝试制作一个自定义钩子,该钩子将连接数组并删除重复的对象。我只希望钩子在道具发生变化时运行该进程,以避免不需要的处理。
我试图缓存连接的结果,并使用useMemo
仅在更改但不起作用时运行。显然,我对useMemo
的工作方式有所欠缺。
我尝试了各种方法,主要是围绕一些细微的调整,例如向useMemo
依赖项添加数组,而不是合并。任何帮助都会很棒。谢谢
import * as React from "react";
let merged: any = [];
let result: any = [];
export const useRemoveDuplicateObjects = (arrays: any, value: string) => {
merged = arrays.flat();
const key = (item: any) => {
return item[value];
};
const process = () => {
result = [...new Map(merged.map((item: any) => [key(item), item])).values()];
};
React.useMemo(() => {
if (merged.length) {
process();
}
}, [merged]);
return [result];
};
这里很少有事情做得不好。
首先,当您将数组作为第二个参数传递给useMemo
时,React会将其值与严格相等进行比较,即===
。比较每次都会失败,因为您重新分配了merged
变量每次挂钩运行时。
如果你想比较数组中包含的以前的值和新的值,我可以想到两种方法:
- 直接传递
merged
作为第二个参数,而不是将其放入在一个数组中,React将通过这种方式比较其中的值直接地我不确定这是否可行,因为也许值不会总是按相同的顺序排列 - 您可以存储";旧的";每次挂钩时数组的值运行(例如使用
useState
挂钩(并比较这个旧的值,然后设置布尔值照着这样,这个布尔值可以作为第二个数组中的参数添加到useMemo
此外,正如文档所述,使用Memo"昂贵地返回计算值";。所以,为了配合它的工作方式,你应该";结果";值是这样的:
const result = React.useMemo(() => {
if (merged.length) {
return [...new Map(merged.map((item: any) => [key(item), item])).values()]
}
return []
}, merged); // will or won't work, I'd say go with the comparison yourself as stated before
最后,如果你只想从钩子中返回一个值,就不需要把它包装在数组中,你可以这样做:
return result;