I wrote a code that receives the api through React Hook and calls the api again in the child ponent by passing the id when clicking. However, there seems to be a problem in settingState with arrow function in useEffect or onClick of child ponent.
I would appreciate it if you could give me an answer on how to fix it.
Users.js
import axios from 'axios';
import React, { useState, useEffect } from 'react';
import UserInfo from './UserInfo';
function Users() {
const [users, setUsers] = useState(null)
const [loding, setLoding] = useState(false)
const [error, setError] = useState(false)
const [userId, setUserId] = useState(null)
const fetchUsers = async () => {
try {
setUsers(null)
setError(null);
setLoding(true)
const respnse = await axios.get('')
setUsers(respnse)
} catch (e) {
setError(e)
}
setLoding(false)
};
useEffect(() => {
fetchUsers();
}, []);
if (loding) return <div>loading...</div>
if (error) return <div>error....</div>
if (!users) return null;
return (
<>
<ul>
{
users.data.map(user =>
<li key={user.id} onClick={() => setUserId(user.id)} >
{user.username} ({user.name})
</li>
)
}
</ul>
<button onClick={fetchUsers}>
reload
</button>
{userId && <UserInfo id={userId} />}
</>
);
}
export default Users;
UserInfo.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function UserInfo({ id }) {
const [userInfo, setUserInfo] = useState(null)
async function getUsersAPI() {
try {
const response = await axios.get(`/${id}`)
setUserInfo(response)
} catch (e) {
}
}
useEffect(() => {
getUsersAPI()
}, [userInfo])
if (!userInfo) {
return null;
}
const { data } = userInfo
return (
<>
<h2>{data.username}</h2>
<p>
<b>email: </b>{data.email}
</p>
</>
);
}
export default UserInfo;
I wrote a code that receives the api through React Hook and calls the api again in the child ponent by passing the id when clicking. However, there seems to be a problem in settingState with arrow function in useEffect or onClick of child ponent.
I would appreciate it if you could give me an answer on how to fix it.
Users.js
import axios from 'axios';
import React, { useState, useEffect } from 'react';
import UserInfo from './UserInfo';
function Users() {
const [users, setUsers] = useState(null)
const [loding, setLoding] = useState(false)
const [error, setError] = useState(false)
const [userId, setUserId] = useState(null)
const fetchUsers = async () => {
try {
setUsers(null)
setError(null);
setLoding(true)
const respnse = await axios.get('https://jsonplaceholder.typicode./users')
setUsers(respnse)
} catch (e) {
setError(e)
}
setLoding(false)
};
useEffect(() => {
fetchUsers();
}, []);
if (loding) return <div>loading...</div>
if (error) return <div>error....</div>
if (!users) return null;
return (
<>
<ul>
{
users.data.map(user =>
<li key={user.id} onClick={() => setUserId(user.id)} >
{user.username} ({user.name})
</li>
)
}
</ul>
<button onClick={fetchUsers}>
reload
</button>
{userId && <UserInfo id={userId} />}
</>
);
}
export default Users;
UserInfo.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function UserInfo({ id }) {
const [userInfo, setUserInfo] = useState(null)
async function getUsersAPI() {
try {
const response = await axios.get(`https://jsonplaceholder.typicode./users/${id}`)
setUserInfo(response)
} catch (e) {
}
}
useEffect(() => {
getUsersAPI()
}, [userInfo])
if (!userInfo) {
return null;
}
const { data } = userInfo
return (
<>
<h2>{data.username}</h2>
<p>
<b>email: </b>{data.email}
</p>
</>
);
}
export default UserInfo;
Share
Improve this question
edited Aug 7, 2021 at 8:19
Drew Reese
204k18 gold badges246 silver badges274 bronze badges
asked Aug 7, 2021 at 8:14
dev_Odev_O
1633 silver badges13 bronze badges
3
-
3
why is
userInfo
in the dependency array foruseEffect
? – ksav Commented Aug 7, 2021 at 8:17 - It is implemented so that it can have useinfo information through the api. If I'm wrong, please give me another answer. – dev_O Commented Aug 7, 2021 at 8:21
-
1
getUsersAPI
updates theuserInfo
state, which as a dependency, triggers theuseEffect
hook's callback to again callgetUsersAPI
, thus creating a render loop. When do you actually want the effect in the child to run? If I had to guess, it should be theid
prop that is passed since that is referenced in thegetUsersAPI
call. – Drew Reese Commented Aug 7, 2021 at 8:21
3 Answers
Reset to default 4It seems like you want id
to be a useEffect
dependency instead of userInfo.
Otherwise every time userInfo
changes the effect will run, it will call getUsersAPI
which in turns sets the value of userInfo
when axios resolves (thus causing an infinite loop).
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function UserInfo({ id }) {
const [userInfo, setUserInfo] = useState(null)
async function getUsersAPI() {
try {
const response = await axios.get(`https://jsonplaceholder.typicode./users/${id}`)
setUserInfo(response)
} catch (e) {}
}
useEffect(() => {
getUsersAPI()
}, [id])
if (!userInfo) {
return null;
}
const { data } = userInfo
return (
<>
<h2>{data.username}</h2>
<p>
<b>email: </b>{data.email}
</p>
</>
);
}
export default UserInfo;
this problem is due to the fact that you have set userInfo
as a dependency for useEffect
dependency array! every time this ponent renders, useEffect will call your API and it changes the value of userInfo, so you encounter with infinite loop!
The problem is in the UserInfo.js file. In these lines:
useEffect(() => {
getUsersAPI()
}, [userInfo])
You fetch userInfo but then setUserInfo(response)
again which cause useEffect to run again.
If might want to leave it as:
useEffect(() => {
getUsersAPI()
}, [])
So the useEffect only run once. Or you want it to reflect your last userId from props then put userId to the dependency array:
useEffect(() => {
getUsersAPI()
}, [id])
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745348118a4623657.html
评论列表(0条)