我试图从API提取数据并设置数据状态,但是当我在子组件中使用数据时,会收到[Unhandled promise rejection: TypeError: null is not an object (evaluating 'data.name')]
警告。
这里是我要做的要点。有谁知道为什么会这样?我认为这是因为未从API接收数据。我尝试添加“ isLoading”状态,并且仅在返回false时才返回ChildComponent,但是我仍然收到相同的警告(这可能是因为useEffect中的setNewProp在从API接收数据时未更新)。
const ParentComponent = (props) => {
const [data, setData] = useState(null);
const [newProp, setNewProp] = useState();
const fetchData = async () => {
new DataService.retrieveData().then((response) => {
setData(response);
}
}
useEffect(() => {
fetchData();
setNewProp({ data, ...props });
}, []);
return (
<ChildComponent newProp={newProp} />
);
}
答案 0 :(得分:4)
您不能在useEffect生命周期事件内使用异步函数。作为一个好的解决方案,我建议充分利用useEffect挂钩并将其用作对更新数据的影响。
const ParentComponent = (props) => {
const [data, setData] = useState(null);
const [newProp, setNewProp] = useState();
const fetchData = async () => {
new DataService.retrieveData().then((response) => {
setData(response);
}
}
useEffect(() => {
fetchData();
}, []);
useEffect(() => {
setNewProp({ data, ...props });
}, [data]);
return (
<ChildComponent newProp={newProp} />
);
}
我还要指出,useEffect在第一个渲染之后运行。这意味着您的ChildComponent将始终收到“ undefined”作为第一个道具,因为在以下位置没有设置初始值:
const [newProps, setNewProp] = useState(); // initial value comes here to prevent errors
答案 1 :(得分:0)
看起来您可能错过了await
中使代码等到提取完成之前所需的useEffect()
:
之前:
useEffect(() => {
fetchData();
setNewProp({ data, ...props });
}, []);
之后:
useEffect(() => {
(async () => {
await fetchData();
setNewProp({ data, ...props });
})();
}, []);
请注意,useEffect()
不支持异步函数(因为它需要将返回值用作清理函数或未定义。例如,请参见this article。
但更好的可能是这样的:
const [data, setData] = useState(null);
const fetchData = async () => {
new DataService.retrieveData().then((response) => {
setData(response);
}
}
fetchData();
if (data) {
const newProp = { data, ...props };
}
答案 2 :(得分:0)
在代码中,您首先调用fetchData函数,该函数完成后将调用useState挂钩。由于useState挂钩是异步工作的,因此状态data
不会立即更改。
useEffect(() => {
fetchData(); // Called setData()
setNewProp({ data, ...props }); // At this point, data hasn't changed yet.
}, []);
因此,您可以再次使用useEffect挂钩来监视data
状态下的更改。然后,您应该设置newProp
的新状态。
useEffect(() => {
(async () => {
await fetchData();
})();
}, []);
useEffect(() => {
setNewProp({...props, data });
}, [data]);