我正在尝试以某种形式加载从API获得的一些数据,但是状态挂钩似乎做错了。
在下面的代码中,我使用钩子定义一个employee和employeeId。
之后,我尝试使用useEffect
来模仿类组件中的componentDidMount函数。
在这里,我会检查url中是否包含参数,并使用setEmployeeId(props.match.params.employeeId)
更新employeeId状态。
问题是,我的状态值没有更新,我的整个流程都崩溃了。
请记住,我宁愿为此使用功能组件。
export default function EmployeeDetail(props) {
const [employeeId, setEmployeeId] = useState<number>(-1);
const [isLoading, setIsLoading] = useState(false);
const [employee, setEmployee] = useState<IEmployee>();
useEffect(() => componentDidMount(), []);
const componentDidMount = () => {
// --> I get the correct id from the params
if (props.match.params && props.match.params.employeeId) {
setEmployeeId(props.match.params.employeeId)
}
// This remains -1, while it should be the params.employeeId
if (employeeId) {
getEmployee();
}
}
const getEmployee = () => {
setIsLoading(true);
EmployeeService.getEmployee(employeeId) // --> This will return an invalid employee
.then((response) => setEmployee(response.data))
.catch((err: any) => console.log(err))
.finally(() => setIsLoading(false))
}
return (
<div>
...
</div>
)
}
答案 0 :(得分:0)
从useEffect
返回的函数将在onmount上调用。由于您使用的是隐式收益,因此您的情况就是如此。如果需要在挂载上调用它,则需要调用它而不是返回它。
编辑:由于还设置了员工ID,因此需要在依赖项数组中进行跟踪。这是因为,React中的设置状态是异步的,并且更新的状态值仅在下一个渲染器上可用。
useEffect(() => {
componentDidMount()
}, [employeeId]);
一种替代方法是直接通过getEmployee
方法使用props的数据:
useEffect(() => {
componentDidMount()
}, []);
const componentDidMount = () => {
if (props.match.params && props.match.params.employeeId) {
setEmployeeId(props.match.params.employeeId)
getEmployee(props.match.params.employeeId);
}
}
const getEmployee = (employeeId) => {
setIsLoading(true);
EmployeeService.getEmployee(employeeId);
.then((response) => setEmployee(response.data))
.catch((err: any) => console.log(err))
.finally(() => setIsLoading(false))
}
答案 1 :(得分:0)
来自setEmployeeId
的新值可能会在下一个渲染中可用。
您正在运行的代码是同一渲染的一部分,因此尚未设置该值。
由于您使用的是同一函数,请使用已经拥有的值:props.match.params.employeeId
。
请记住,当您调用set*
时,是在指示React将更新排队。当React决定时,更新可能会发生。
如果您希望getEmployee
仅运行一次currentEmployeeId
更改,请考虑使其生效:
useEffect(() => {
getEmployee(currentEmployeeId);
}, [currentEmployeeId])
答案 2 :(得分:0)
问题似乎是您尝试在更新之前使用“已更新”状态。我建议您使用类似的
export default function EmployeeDetail(props) {
const [employeeId, setEmployeeId] = useState<number>(-1);
const [isLoading, setIsLoading] = useState(false);
const [employee, setEmployee] = useState<IEmployee>();
useEffect(() => componentDidMount(), []);
const componentDidMount = () => {
// --> I get the correct id from the params
let currentEmployeeId
if (props.match.params && props.match.params.employeeId) {
currentEmployeeId = props.match.params.employeeId
setEmployeeId(currentEmployeeId)
}
// This was remaining -1, because state wasn't updated
if (currentEmployeeId) {
getEmployee(currentEmployeeId);
//It's a good practice to only change the value gotten from a
//function by changing its parameter
}
}
const getEmployee = (id: number) => {
setIsLoading(true);
EmployeeService.getEmployee(id)
.then((response) => setEmployee(response.data))
.catch((err: any) => console.log(err))
.finally(() => setIsLoading(false))
}
return (
<div>
...
</div>
)
}