#reactjs #react-hooks
#reactjs #реагирующие хуки
Вопрос:
Я вызываю функцию ( getEmployees(url)
) внутри a useEffect
без второго аргумента.
Я хочу вызывать getEmployees(url
) каждый раз employee
, когда добавляется. Как только я добавляю employee
или error
в качестве второго аргумента, useEffect
повторный рендеринг выполняется бесконечно.
Так ли это должно работать?
import React, { useEffect, useState, useCallback } from 'react'
//
import EmployeeRecord from './EmployeeRecord'
const Employees = () => {
const [loading, setLoading] = useState(false);
const [employees, setEmployees] = useState([]);
const [error, setError] = useState({show: false, msg: ''});
//
const url = 'http://localhost:3001/';
//
// const fetchDrinks = useCallback( async () => {
const getEmployees = useCallback( async (url) => {
setLoading(true)
try {
const response = await fetch(url)
const data = await response.json()
if (data) {
setEmployees(data)
setError({ show: false, msg: '' })
} else {
setError({ show: true, msg: data.Error })
}
setLoading(false)
} catch (error) {
console.log(error)
}
}, []);
useEffect(() => {
getEmployees(url)
}, [])
console.log("11111111 from employee.js ")
if (loading){
return (
<div>
.....is loading
</div>
)
}
return (
<div>
<div className="addinfo-infomations">
<EmployeeRecord employees={employees}/>
</div>
</div>
)
}
export default Employees
Комментарии:
1. К какому крючку вы добавляете аргумент, который вызывает бесконечный рендеринг?
Ответ №1:
Второй аргумент useEffect
— это список зависимостей, указывающий React повторно вызывать вашу useEffect
функцию при каждом изменении одной из зависимостей.
Если нет зависимостей ( []
), он просто запустится при монтировании компонента.
Прямо сейчас, если вы ставите employees
как зависимость, она будет меняться каждый раз, когда устанавливается ваш employees
массив. И вы можете видеть, что в вашей getEmployees
функции, которую вы вызываете setEmployees
. Вот как вы оказываетесь в своем цикле:
useEffect -> getEmployees -> setEmployees -> (employees changes, triggering useEffect again)
Чтобы избежать этого, вы не должны создавать цикл или каким-то образом замыкать его.
Вы говорите, что хотите запускать getEmployees
каждый раз при добавлении сотрудника, но из того, что вы показали, нет кода, касающегося добавления сотрудника. Итак, я предполагаю, что, возможно, это происходит на сервере, который вы опрашиваете? Если это так, вам нужно будет найти какой-то способ получить уведомление от сервера — это не будет вопросом простого вызова useEffect
, потому что у React не будет возможности узнать, что был добавлен сотрудник. Или в вашем примере отсутствует какой-то соответствующий код.
Ответ №2:
вызовите getEmployees
причину employees
и error
измените. Если вы добавляете сотрудника или ошибку в качестве второго аргумента, это означает, что useEffect выполнит обратный вызов при employees
error
изменении и . В результате useEffect выполнит обратный вызов при вашем вызове getEmployees
. Затем будет вызван обратный вызов getEmployees
useEffect . произошла бесконечность.
Я думаю, если вы хотите перезагрузить empolyees, вы можете добавить кнопку обновления
const [refresh, setRefresh] = React.useState(true);
const doRefresh = React.useCallback(() => {
setRefresh(pre => !pre);
}, []);
useEffect(() => {
...
}, [refresh]);
return (
<div>
...
<button onClick={doRefresh}>reload</button>
</div>
)
или автоматическая перезагрузка
useEffect(() => {
let handle;
const task = () => {
getEmpolyees().then(() => {
handle = setTimeout(task, 1000)
});
}
task();
return () => {
handle amp;amp; clearTimeout(handle);
}
}, [])
Ответ №3:
Я чувствую, что сотрудники, которые добавляются к данным, которые вы получаете обратно, fetch
должны отличаться, и если они разные, вам нужно их разделить, чтобы это работало так, как у вас есть сейчас. Добавления другого состояния для него было бы достаточно, допустим, мы вызываем его setData
, поскольку у вас есть его имя data
. Теперь setData
вместо employees таким образом эффект не запускает бесконечный цикл, а затем обновляет эффект со всеми его зависимостями, и у вас не будет проблем.
const Employees = () => {
const [loading, setLoading] = useState(false);
const [employees, setEmployees] = useState([]);
const [data, setData] = useState();
const [error, setError] = useState({ show: false, msg: '' });
//
const url = 'http://localhost:3001/';
//
// const fetchDrinks = useCallback( async () => {
const getEmployees = useCallback(async url => {
setLoading(true);
try {
const response = await fetch(url);
const data = await response.json();
if (data) {
setData(data)
setError({ show: false, msg: '' })
} else {
setError({ show: true, msg: data.Error });
}
setLoading(false);
} catch (error) {
console.log(error);
}
}, []);
useEffect(() => {
url amp;amp; getEmployees(url);
}, [url, employees, getEmployees]);
if (loading) {
return <div>.....is loading</div>;
}
return (
<div>
<div className="addinfo-infomations">
<EmployeeRecord employees={employees} data={data} />
</div>
</div>
);
};