使用数组作为依赖项获取 useEffect 中的数据只应在新元素上调用



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

此数组使用useState挂钩保存在名为Parent的组件中。每当我想添加新项目时,我都必须重新创建数组,因为我不允许直接改变它。

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

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 中仅为新元素获取新数据,而不是再次为整个数组获取新数据?

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

不如在Parent中获取 API 数据并将最终结果传递给Child?这种重构将提供一些好处:

  • Parent拥有 items 数组状态,并且知道何时何地添加新项。这使得增量fetch变得非常容易。您还可以免费划分容器和表示组件。
  • 获取的 API 数据与项目数组相关。您可能希望以某种方式将它们一起使用(将 api 数据另存为状态、组合它们等)。这个星座将促进派生状态,这是一种更容易出错的模式。

类似于以下示例的内容已经可以做您想要的事情 - 通过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钩子记住你的孩子中以前的数组属性,并寻找项目的变化。

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;
}

代码沙盒

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

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

相关内容

最新更新