如何获取数据并在useEffect()中使用它?

时间:2020-07-02 17:49:04

标签: reactjs react-native

我试图从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} />

        );
}

3 个答案:

答案 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]);