开发者问题收集

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

2020-07-02
827

我尝试从 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个回答

您不能在 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”作为第一个 props,因为没有设置初始值:

const [newProps, setNewProp] = useState(); // initial value comes here to prevent errors
Jan-Philipp Marks
2020-07-02

看起来您可能错过了 useEffect() 中所需的 await ,以使代码等到提取完成:

之前:

useEffect(() => {
  fetchData();
  setNewProp({ data, ...props });
}, []);

之后:

useEffect(() => {
  (async () => {
    await fetchData();
    setNewProp({ data, ...props });
  })();
}, []);

请注意, useEffect() 不支持异步函数(因为它需要返回值为清理函数或未定义。例如,请参阅 这篇文章

但更好的可能是这样的:

const [data, setData] = useState(null);
const fetchData = async () => {
  new DataService.retrieveData().then((response) => {
    setData(response);
  }
}

fetchData();
if (data) {
  const newProp = { data, ...props };
}
tar
2020-07-02

在您的代码中,您首先调用 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]);
Mertcan Seğmen
2020-07-02