Matteo Scaldaferri
Matteo Scaldaferri

Reputation: 13

ReactJS how to update page after fetching data

I'm new to ReactJS and I'm now trying to do an interactive comments section (taken from frontendmentor.io), but the App component just doesn't show what it's supposed to show

This is my App component:

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

    useEffect(() => {
        const getComm = async () => {
            await fetchData();
        };

        getComm();
    }, []);
    console.log(data);

    const fetchData = async () => {
        const res = await fetch("db.json").then(async function (response) {
            const comm = await response.json();
            setData(comm);
            return comm;
        });
    };
    return (
        <Fragment>
            {data.length > 0 ? <Comments data={data} /> : "No Comments to Show"}
        </Fragment>
    );
}

export default App;

The console.log(data) logs two times:

As it follows: console.log(data)

If I force the App to print the Comments it just says that cannot map through an undefined variable

the error when displaying "Comments" component

This is my Comments component:

function Comments({ data }) {
    return (
        <div>
            {data.map((c) => (
                <Comment key={c.id} />
            ))}
        </div>
    );
}

export default Comments;

I'm wondering why the page still displays No Comments to Show even if the log is correct

Upvotes: 1

Views: 1824

Answers (2)

Fiodorov Andrei
Fiodorov Andrei

Reputation: 2018

@Cristian-Irimiea Have right about response get from fetch. Response is an a object and can't be iterate. You need to store in state the comments from response

But you have multiple errors:

  1. Take a look how use async function. Your function fetchData looks bad.
// Your function
const fetchData = async () => {
        const res = await fetch("db.json").then(async function (response) {
            const comm = await response.json();
            setData(comm);
            return comm;
        });
    };

// How can refactor
// fetchData function have responsibility to only fetch data and return a json
const fetchData = async () => {
  const response = await fetch("./db.json");
  const body = await response.json();

  return body;
};

  1. You are updating state inside fetch function but a good solution is update state then promise resolve:
useEffect(() => {
  // here we use .then to get promise response and update state
  fetchData().then((response) => setData(response.comments));
}, []);

Upvotes: 1

Cristian Irimiea
Cristian Irimiea

Reputation: 111

The initial state of your data is an array.

After you fetch your data from the response you get an object. Changing state types is not a good practice. You should keep your data state as an array or as an object.

Considering you will keep it as an array, you need use an array inside of setData. Ex.

comm && Array.isArray(comm.comments) && setData(comm.comments);

As for your Comments component you should consider expecting an array not an object.

Ex.

function Comments(data) {
    return (
        <div>
            {data.map((c) => (
                <Comment key={c.id} />
            ))}
        </div>
    );
}

export default Comments;

Upvotes: 1

Related Questions