首页 > 解决方案 > 仅应在新元素上调用使用数组作为依赖项的 useEffect 中的数据

问题描述

我有一个数组,它作为道具提供给我的名为Child. 现在,每次将新项目添加到数组时,都应该针对 API 进行提取。

这个数组保存在一个Parent使用useState钩子命名的组件中。每当我想添加一个新项目时,我都必须重新创建数组,因为我不允许直接对其进行变异。

我试图在以下代码片段中简化我的用例:

const Parent = () => {
    const [array, setArray] = useState([]);

    ///...anywhere
    setArray(a => [...a, newItem]);

    return <Child array={array} />;
}

const Child = ({ array }) => {
    useEffect(() => {
        array.forEach(element => {
            fetch(...);    
        });
    }, [array]);

    return ...;
}

现在,我的问题是:我怎样才能从我的 API 中只为新元素而不是整个数组获取新数据?

我希望我足够好地描述了我的问题。如果有任何不清楚或遗漏的地方,请告诉我。

标签: reactjsreact-hooksuse-effect

解决方案


如何取而代之的是获取 API 数据Parent并将最终结果传递给Child?这种重构会带来一些好处:

像下面的例子这样的东西已经可以做你想做的了——通过onClick(或以其他方式)添加一个项目,获取它的数据并将整个数组传递给 Child:

const Parent = () => {
  const [array, setArray] = useState([]);

  return (
    <div onClick={addItem}>
      <Child array={array} />;
    </div>
  );

  function addItem(e) {
    const item = createItemSomehow(...)
    fetch(...).then(data => setArray([...array, { item, data }]));
  }
};

更新:

如果你想保持你的结构和 API 不变,另一种方法是用usePrevious钩子记住你的 Child 中的先前数组 prop 并查找项目更改。

const Child = ({ array }) => {
  const prevArray = usePrevious(array);
  useEffect(() => {
    if (array !== prevArray && array.length) {
      //fetch(...)
      console.log(`fetch data for index ${array.length - 1}`);
    }
  });
  return (...);
};

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

密码沙盒


推荐阅读