我有一个数组,该数组作为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中获取新数据?
我希望我对问题的描述足够好。如果有任何不清楚或遗漏的地方,请告诉我。
答案 0 :(得分:1)
取而代之的是获取Parent
中的API数据并将最终结果传递给Child
呢?重构将带来一些好处:
Parent
owns the items array state,知道何时何地添加新项目。这使得增量fetch
非常容易。您还可以免费获得container and presentational components的划分。类似以下示例的内容已经可以做您想要的事情-通过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;
}
答案 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]);