首页 > 解决方案 > 道具更改时反应自定义挂钩运行过程

问题描述

我是 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];
};

标签: javascriptreactjstypescriptreact-hooks

解决方案


这里很少有事情做得不好。

对于初学者,当您将数组作为第二个参数传递给 时useMemo,React 会将其值与严格相等进行比较,即===. 每次比较都会失败,因为merged每次运行钩子时都会重新分配变量。

如果要比较数组包含的先前值和新值,我可以想到两种方法:

  1. 直接merged作为第二个参数传递,而不是将其放入数组中,这样 React 将直接比较其中的值。我不确定这是否可行,因为这些值可能并不总是相同的顺序。
  2. 您可以在每次钩子运行时存储数组的“旧”值(useState例如使用钩子),然后自己将这个旧值与新值进行比较,然后相应地设置一个布尔值。这样,这个布尔值可以作为数组中的第二个参数传递给您的useMemo.

此外,正如文档所述, useMemo “返回一个昂贵的计算值”。因此,要了解它的工作原理,您应该以这种方式获得“结果”值:

   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;

推荐阅读