【问题标题】:Hooks in react are not updating my state correctly反应中的钩子没有正确更新我的状态
【发布时间】:2020-03-09 08:37:43
【问题描述】:

我正在尝试以表单的形式加载从 API 获得的一些数据,但我的状态挂钩似乎有问题。

在下面的代码中,我使用挂钩来定义员工和员工 ID。 之后,我尝试使用 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>
    )
}

【问题讨论】:

  • setEmployeeId 的新值可能在下一次渲染中可用。您正在运行的代码是同一渲染的一部分,因此尚未设置该值。因为你在同一个函数中,所以使用你已经拥有的值props.match.params.employeeId。请记住,当您调用 set* 时,您是在指示 React 将更新排队。更新可能会在 React 决定时发生。

标签: reactjs react-functional-component


【解决方案1】:

useEffect 返回的函数将在挂载时调用。由于您使用的是隐式返回,这就是您的情况。如果您需要在挂载时调用它,则需要调用它而不是返回。

编辑:由于您还设置了员工 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))
}

【讨论】:

【解决方案2】:

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

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

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

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

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

useEffect(() => {
   getEmployee(currentEmployeeId);
}, [currentEmployeeId])

【讨论】:

    【解决方案3】:

    问题似乎是您试图在更新之前使用“更新”状态。我建议你使用类似的东西

    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>
        )
    }
    

    【讨论】:

      猜你喜欢
      • 2020-04-26
      • 2021-02-12
      • 2021-01-31
      • 1970-01-01
      • 2020-07-12
      • 1970-01-01
      • 1970-01-01
      • 2021-11-12
      • 1970-01-01
      相关资源
      最近更新 更多