我在 getEmployees(url)
中调用一个函数 (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
答案 0 :(得分:0)
useEffect
的第二个参数是一个依赖项列表,告诉 React 在任何依赖项发生变化时再次调用您的 useEffect
函数。
如果没有依赖项([]
),它会在组件挂载时运行。
现在,如果您将 employees
作为依赖项,则每次设置 employees
数组时它都会更改。而且,您可以看到在您的 getEmployees
函数中,您调用了 setEmployees
。这就是你最终进入循环的方式:
useEffect -> getEmployees -> setEmployees -> (employees changes, triggering useEffect again)
为了避免这种情况,您必须不形成回路,或以某种方式将其短路。
您说每次添加员工时都想运行 getEmployees
,但是您所展示的代码中没有处理添加员工的代码。所以,我假设这可能发生在您正在轮询的服务器上?如果是这样,您将需要找到某种方法从服务器获取通知——这不仅仅是调用 useEffect
的问题,因为 React 将无法知道添加了一名员工.或者,您的示例缺少一些相关代码。
答案 1 :(得分:0)
调用 getEmployees
会导致 employees
和 error
发生变化。如果您添加员工或错误作为第二个参数,则意味着 useEffect 将在 employees
和 error
更改时执行其回调。因此,当您调用 getEmployees
时,useEffect 将执行其回调。然后 useEffect 的回调会调用 getEmployees
。无穷大发生了。
我想如果你想重新加载员工,你可以添加一个刷新按钮
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 && clearTimeout(handle);
}
}, [])
答案 2 :(得分:0)
我觉得添加的员工与您从 fetch
返回的数据应该不同,如果他们不同,您需要将它们分开,以便按照您现在的方式工作.为它添加另一个状态就足够了,假设我们将其命名为 setData
,因为您将其命名为 data
。您现在可以使用 setData
而不是员工,这样效果不会启动无限循环,然后使用其所有依赖项更新效果,您就没有问题了。
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 && 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>
);
};