简体   繁体   中英

React Async Function wrapped in a UseEffect

I am confused on how an async function works.

The console.log returns an error because the data.rates does not exist yet. But I thought because the useEffect function is async anything under it would be called after the async is over.

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. So the console.log(data.rates) gets executed and then once the component is mounted the callback passed to useEffect is executed. 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.

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. You would typically provide a "loading" state while data is stale.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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