包裹在 UseEffect 中的 React 异步函数

IT技术 javascript reactjs async-await
2021-05-24 08:53:55

我对异步函数的工作方式感到困惑。

console.log 返回错误,因为 data.rates 尚不存在。但我认为因为 useEffect 函数是异步的,所以在异步结束后会调用它下面的任何东西。

function App() {
  const [data, setData] = useState();

  useEffect(() => {
    (async () => {
      const result = await axios.get(
        "https://open.exchangerate-api.com/v6/latest"
      );
      setData(result.data);
    })();
  }, []);

  console.log(data.rates); <-- Error data.rates does not exist
  return <div>{!data ? "Loading..." : "Hello"}</div>;
}
3个回答

我觉得没有一个答案真正回答了这个问题。

useEffect不会停止执行流程,您在传递给它的回调中做什么并不重要。所以console.log(data.rates)会被执行,然后一旦组件被挂载,传递给的回调就会useEffect被执行。由于回调( setData(result.data))中的状态正在改变,这会触发重新渲染,这次您应该看到正确的值被记录下来,没有任何错误。

您的假设实际上是正确的,这种情况下的 useEffect 将在安装Component 时运行,这意味着console.log将被调用两次 - 首先使用初始值(未定义),其次是在实际设置数据时 useEffect 执行副作用( setData) 请求完成后。您通常会在数据陈旧时提供“加载”状态。

function App() {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState();

  useEffect(() => {
    (async () => {
      setLoading(true);
      const result = await axios.get(
        "https://open.exchangerate-api.com/v6/latest"
      );
      setLoading(false);
      setData(result.data);
    })();
  }, []);

  if (loading) return <div>Fetching data...</div>

  return <div>Hello</div>;
}

尝试这样做(我已经创建了一个解决方法)

function App() {
    const [data, setData] = useState();

    useEffect(()=>{
        const setObtainedData=async()=>{
            const result = await axios.get("https://open.exchangerate-api.com/v6/latest");
            setData(result.data);
        };
        setObtainedData();
    },[]);

    if(data){
        console.log(data.rates);
    }
    return <div>{!data ? "Loading..." : "Hello"}</div>;
};