0

我正在尝试以表单的形式加载从 API 获得的一些数据,但我的状态挂钩似乎做错了什么。

在下面的代码中,我使用挂钩来定义员工和员工 ID。之后,我尝试使用useEffect类组件来模仿 componentDidMount 函数。

进入这里后,我检查 url 中是否有参数,并使用setEmployeeId(props.match.params.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>
    )
}
4

3 回答 3

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))
}
于 2019-11-13T14:10:54.643 回答
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>
    )
}
于 2019-11-13T14:22:36.297 回答
0

新值setEmployeeId可能在下一次渲染中可用。

您正在运行的代码是同一渲染的一部分,因此尚未设置该值。

由于您在同一个函数中,请使用您已经拥有的值:props.match.params.employeeId

请记住,当您调用时,set*您是在指示 React 将更新排队。更新可能会在 React 决定时发生。

如果您希望getEmployee只运行一次currentEmployeeId更改,请考虑将其置于其自身的效果中:

useEffect(() => {
   getEmployee(currentEmployeeId);
}, [currentEmployeeId])
于 2019-11-13T14:22:04.723 回答