简体   繁体   中英

React Axios with UseEffect not rendering data

I have been struggling myself silly to get data read from a local json file and fed into a React render function. I first read the code in via a class through the componentDidMount method, but the data always arrived later than the render function executed. I have looked at a number of solutions. Most people seem to recommend the use of useEffect and useState to get around this issue.

This is what I have so far:

import React, {useEffect, useState} from 'react';
import axios from "axios";

export default function Foo() {
    const [list, setProjects] = useState(null)

    useEffect(() => {
        axios.get('data.json')
            .then(response => {
                setProjects(response.data)
            })
    }, [])

    console.log(list);
    debugger;

    if (list !== null) {
        return (
            <div>
                Project: {/*{list.projects[0].title}*/}
            </div>
        )
    } else {
        return (
            <div>
                Loading Project Data ...
            </div>
        )
    }
}

The incoming data comes in the format {"projects": [{"id": 1, "title": "some title", ...}, ... {...}]} .

Issue is, even though I have a null check wrapping around the return, the code always jumps into the first branch, and complains that there is nothing (nothing is shown with Project: {list} and Project: {list.projects[0].title} errors because list is deemed to be null). The console shows the data loading, but I suspect there is an async issue at play related to the promise. I have tuned the initial state, but no luck so far.

在此处输入图像描述

在此处输入图像描述

EDIT:

Thank you to all the replies received. Whilst they helped to streamline the code and added extra checks, I still had the same issue with the data not being displayed. It seems the problem lay with the initial value I assigned. I changed these to:

const [list, setProjects] = useState({projects: [{title: "XXX"}]});

And the code worked fine. I guess this dummy value gets overwritten by the actual json vales once these became available.

try create another state

 const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); axios.get('data.json').then(response => { setProjects(response.data); setLoading(false); }) }, []) if (loading) { else{ }

Try using another variable isLoading, when the axios works to fetch the data set it to true and the after the response set it to False. Try the following code:

import React, {useEffect, useState} from 'react';
import axios from "axios";

export default function Foo() {
    const [list, setProjects] = useState(null);
    const [isLoading, setIsLoading] = useState(false);

    useEffect(() => {
       setIsLoading(true);
       axios.get('data.json')
         .then(response => {
           setProjects(response.data);
           setIsLoading(false);
                    })
         }, []);
console.log(list);
debugger;
return (
<React.Fragment>
{isLoading && <h1>Loading Data.........</h1>}
{!isLoading && (<div> Project: {/*{list.projects[0].title}*/}</div>)}
</React.Fragment>
);
}

Instead of this:

if (list !== null) {
    return (
        <div>
            Project: {/*{list.projects[0].title}*/}
        </div>
    )
} else {
    return (
        <div>
            Loading Project Data ...
        </div>
    )
}

I would do something like this:

return (
  <div>
    {list && list.projects && list.projects.length > 0 ? (
      <p>{list.projects[0].title}</p>
    ) : (
      <p>Loading Project Data...</p>
    )}      
  </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