仅在新元素上调用使用数组作为依赖项的useEffect中的数据

时间:2019-08-23 06:59:25

标签: reactjs react-hooks use-effect

我有一个数组,该数组作为prop送入名为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中获取新数据?

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

2 个答案:

答案 0 :(得分:1)

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

  • Parent owns the items array state,知道何时何地添加新项目。这使得增量fetch非常容易。您还可以免费获得container and presentational components的划分。
  • 提取的API数据与items数组相关。您可能希望以某种方式一起使用它们(将api数据另存为状态,进行组合等)。这个星座会提升derived state,这是一种更容易出错的模式。

类似以下示例的内容已经可以做您想要的事情-通过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钩子在子级中记住以前的数组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;
}

Codesandbox

答案 1 :(得分:0)

例如,您可以保留以前提取的项目的列表。

const Child = ({ values }) => {

  const [fetched, setFetched] = useState([]);

  useEffect(() => {
    values.forEach(v => {
      if (!fetched.includes(v)) {
        setFetched(fetched => [...fetched, v]);
        fetch(v);
      }
    });
  }, [values, logged]);

https://codesandbox.io/s/affectionate-colden-sfpff