最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Fetching data in React's useEffect() returns "undefined" - Stack Overflow

programmeradmin3浏览0评论

I'm trying to fetch data from a database. It's a get request. All works fine as long I am using the fetched data in the async function. But ouside of it, it just returns "undefined". What am I doing wrong? Thanks for your help :)

const [accountInfos, setAccountInfos] = useState();
      const [error, setError] = useState();
      const [loading, setLoading] = useState(true);

      useEffect(() => {
        (async function runEffect() {
            const fetchedAccountInfos =  await fetchAccountInfos();
            if (fetchedAccountInfos && fetchedAccountInfos.length > 0) {
                console.log(fetchedAccountInfos)  //This console.log works
                setAccountInfos(fetchedAccountInfos);
                setLoading(false);
                console.log(accountInfos)  //This console.log returns 
                                             "undefined"
              } else {
                setError("Accountdaten können nicht geladen werden!");
                setLoading(false);
                };
        })();
      }, []);
      console.log(accountInfos);  //This console.log returns "undefined"

I'm trying to fetch data from a database. It's a get request. All works fine as long I am using the fetched data in the async function. But ouside of it, it just returns "undefined". What am I doing wrong? Thanks for your help :)

const [accountInfos, setAccountInfos] = useState();
      const [error, setError] = useState();
      const [loading, setLoading] = useState(true);

      useEffect(() => {
        (async function runEffect() {
            const fetchedAccountInfos =  await fetchAccountInfos();
            if (fetchedAccountInfos && fetchedAccountInfos.length > 0) {
                console.log(fetchedAccountInfos)  //This console.log works
                setAccountInfos(fetchedAccountInfos);
                setLoading(false);
                console.log(accountInfos)  //This console.log returns 
                                             "undefined"
              } else {
                setError("Accountdaten können nicht geladen werden!");
                setLoading(false);
                };
        })();
      }, []);
      console.log(accountInfos);  //This console.log returns "undefined"
Share Improve this question edited Nov 19, 2019 at 13:04 Nittoc asked Nov 19, 2019 at 12:56 NittocNittoc 431 gold badge1 silver badge5 bronze badges 2
  • accountInfos is set asynchronously, so you cannot expect it to be set until later (outside the scope of where you await the data being fetched). Your code needs to test if the data exists yet or not. – crashmstr Commented Nov 19, 2019 at 13:01
  • You've misunderstood how useState works, once you call a set.. function, your functional ponent will be re-executed and only then that state value will have the new value. – Titus Commented Nov 19, 2019 at 13:02
Add a ment  | 

5 Answers 5

Reset to default 3

It's not React-specific: that's an async function, so the promise is going to resolve after the console log occurs, that's why you get undefined. This is just normal JS behaviour -- the value is undefined at the point console.log executes.

In the return value where you define the JSX, render null (or some empty state ponent) if accountinfos is null, otherwise render the actual ponent based on the return value from the API. Once you get a response, the state will update and the ponent will rerender

You are not doing anything wrong, the console.log outside the useEffect just executes once, on the initial ponent function call, so at that time the accountInfos variable is still undefined.

However, the console.log inside the useEffect is executed after fetching the data so it is defined at that time.

Try this just to see the result?

      const [accountInfos, setAccountInfos] = useState();
      const [error, setError] = useState();
      const [loading, setLoading] = useState(true);

      useEffect(() => {
        (async function runEffect() {
            const fetchedAccountInfos =  await fetchAccountInfos();
            if (fetchedAccountInfos && fetchedAccountInfos.length > 0) {
                setAccountInfos(fetchedAccountInfos);
                setLoading(false);
                console.log(accountInfos)  //This console.log works
              } else {
                setError("Accountdaten können nicht geladen werden!");
                setLoading(false);
                };
        })();
      }, []);
      console.log(accountInfos);  //This console.log returns "undefined"

      useEffect(() => {
        console.log(accountInfos); //check the result here
      }, [accountInfos])

As most of the answers already states the issue it is caused due to, i.e. asynchronous nature of JS. The solution to tackle this issue is simply using a conditional Statement or a ternary operator.

const [accountInfos, setAccountInfos] = useState();
  const [error, setError] = useState();
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    (async function runEffect() {
        const fetchedAccountInfos =  await fetchAccountInfos();
        if (fetchedAccountInfos && fetchedAccountInfos.length > 0) {
            console.log(fetchedAccountInfos)  //This console.log works
            setAccountInfos(fetchedAccountInfos);
            setLoading(false);
            if(accountInfos){
                //console the output only if available
                 console.log(accountInfos);
            }
          } else {
            setError("Accountdaten können nicht geladen werden!");
            setLoading(false);
            };
    })();
  }, []);
  console.log(accountInfos);  //This console.log returns "undefined"

Same approach is useful if rendering the ponent and fetching some data in useEffect hook.

{
   dataIsReturned ? <RenderYourData/> : <h1> Loading </h1>
}

In order to get the updated value and then do some action based on that value, you need to use a useEffect hook

e.g.

const [toggle, setToggle] = useState(false);

useEffect(() => {
   // do something based on new value of toggle
}, [toggle]);

const trigger = () => {
  setToggle(true);
  // OR
  //setToggle(t => !t);
}

发布评论

评论列表(0)

  1. 暂无评论