I want to fetch an array from the backend using a Provider, Context and useEffect:
import React, {useState, useEffect} from 'react'
const UsersContext = React.createContext()
const fetchUsers = async () => {
const url = 'http://localhost:3000/users'
const response = await fetch(url)
console.log('response', await response.json())
return response
}
export const UsersProvider = ({children}) => {
// state
const [users, setUsers] = useState([])
// query data
const data = fetchUsers()
console.log('data', data)
// component updates
useEffect(() => {
if (data) {
// setUsers(data)
}
}, [data])
return (
<UsersContext.Provider value={users}>
{children}
</UsersContext.Provider>
)
}
If I set the users once I have the data back from the backend, I get infinite re-render. The issue is, data is always a promise, although I can see the response after the call is being made:
In the fetchUsers method:
console.log('response', await response.json())
{users: Array(1)}
users: Array(1)
0:
created_at: "2019-10-09T17:41:21.818Z"
email: "ash@email.com"
id: 1
name: "ash"
password_digest: "dafasfae"
updated_at: "2019-10-09T17:41:21.818Z"
In the UsersProvider:
console.log('data', data)
Promise {<pending>}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: Response
body: (...)
bodyUsed: true
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:3000/users"
__proto__: Response
Your data fetch needs to happen inside the useEffect
call. What's happening right now is every time your component renders, you are re-fetching the list of users which causes the data object to change and triggers a re-render. The code below will fetch the data only when the component mounts.
useEffect(() => {
let canceled = false;
const fetchData = async () => {
const users = await fetchUsers();
if (!canceled && data) {
setUsers(data);
}
};
fetchUsers();
return () => { canceled = true; }
}, []);
I would move the fetchUsers function inside the effect and try like this:
import React, { useState, useEffect } from "react";
const UsersContext = React.createContext();
export const UsersProvider = ({ children }) => {
// state
const [users, setUsers] = useState([]);
// component mounts
useEffect(() => {
const fetchUsers = async () => {
const url = "http://localhost:3000/users";
const response = await fetch(url);
const usersData = await response.json();
setUsers(usersData);
};
fetchUsers();
}, []);
return (
<UsersContext.Provider value={users}>{children}</UsersContext.Provider>
);
};
Here is a very good post about fetching data with react hooks:
return only data
const fetchUsers = async () => {
const url = 'http://localhost:3000/users'
const response = await fetch(url)
.then( data => {
return data
})
.catch(err=>console.log(err));
return response;
}
hope this will help you.
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.