简体   繁体   English

React Async Function 包裹在 UseEffect 中

[英]React Async Function wrapped in a UseEffect

I am confused on how an async function works.我对异步 function 的工作原理感到困惑。

The console.log returns an error because the data.rates does not exist yet. console.log 返回错误,因为 data.rates 尚不存在。 But I thought because the useEffect function is async anything under it would be called after the async is over.但我认为因为 useEffect function 是异步的,所以在异步结束后会调用它下面的任何内容。

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>;
}

I feel like none of the answers actually answer the question.我觉得没有一个答案能真正回答这个问题。

useEffect doesn't stop the flow of execution, it doesn't matter what you're doing inside the callback passed to it. useEffect不会停止执行流程,无论您在传递给它的回调中做什么都没关系。 So the console.log(data.rates) gets executed and then once the component is mounted the callback passed to useEffect is executed.所以console.log(data.rates)被执行,然后一旦组件被挂载,传递给useEffect的回调就会被执行。 Since the state is being changed in the callback( setData(result.data) ) this triggers a re-render and this time you should see that the correct value is logged without any errors.由于 state 在回调( setData(result.data) )中被更改,这会触发重新渲染,这一次您应该看到记录了正确的值而没有任何错误。

Your assumption is actually correct, useEffect in this scenario will run when the Component is mounted that means console.log will be called twice--first with initial value (which is undefined), second is after useEffect performed the side-effect when data is actually set (setData) after the request is fulfilled.您的假设实际上是正确的,这种情况下的 useEffect 将在安装组件时运行,这意味着console.log将被调用两次——第一次使用初始值(未定义),第二次是在 useEffect 执行数据时的副作用之后在请求完成后实际设置(setData)。 You would typically provide a "loading" state while data is stale.您通常会在数据过时时提供“加载” state。

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>;
}

Try doing this (I've kind of created a workaround)尝试这样做(我已经创建了一种解决方法)

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>;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM