组件本地状态未使用 React 自定义挂钩更新

Component local state not updating with react custom hooks

我刚开始使用 React Hooks,在使用自定义 Hooks 时遇到了一些问题。这可能是缺乏理解,但这就是我正在尝试的

我的自定义挂钩:

import React, { useState } from "react"

export const useValidateContent = initState => {
    const[valid, setValid] = useState(initState)
    const[errorMsg, setErrorMsg] = useState(null)

    const validate = () => {
      // Update component state to test
      setValid(false)
      setErrorMsg('Some error found')
    }

    return [valid, validate, errorMsg]

}

我使用自定义挂钩的父容器:

import React, { useState, useEffect } from 'react'
import { useValidateContent } from './hooks/useValidateContent'


export default function ParentComp () {

    const [contentIsValid, validate, contentError] = useValidateContent(true)

    const initValidate = () => {
        // values before running validate
        console.log('valid', contentIsValid)
        console.log('error', contentError)
        validate()
        // values after running validate
        console.log('valid', contentIsValid)
        console.log('error', contentError)
    }

    return (
      <div>
        <button onclick={initValidate} />
      </div>
    )
}

我希望在这里得到安慰的是:

valid true
error null
valid false
error Some error found

相反,我看到的是:

valid true
error null
valid true
error null

钩子似乎没有更新本地状态。为什么是这样?即使当我尝试在 hook 组件中控制这些值时,我也会得到同样的结果。我不明白这是为什么。我使用自定义钩子错了吗?

使用钩子更新状态是异步的,就像 class 组件中的 setState 一样,并且由于状态未发生变化 contentIsValidcontentError 仍将引用陈旧的旧状态,而不是新状态。

如果您呈现状态变量,您将看到您的代码按预期工作。

const { useState } = React;

const useValidateContent = initState => {
  const [valid, setValid] = useState(initState);
  const [errorMsg, setErrorMsg] = useState("");

  const validate = () => {
    setValid(false);
    setErrorMsg("Some error found");
  };

  return [valid, validate, errorMsg];
};

function ParentComp() {
  const [contentIsValid, validate, contentError] = useValidateContent(true);

  const initValidate = () => {
    // values before running validate
    console.log("valid", contentIsValid);
    console.log("error", contentError);
    validate();
    // values after running validate
    console.log("valid", contentIsValid);
    console.log("error", contentError);
  };

  return (
    <div>
      <button onClick={initValidate}>initValidate</button>
      contentIsValid: {contentIsValid.toString()}, contentError: {contentError}
    </div>
  );
}

ReactDOM.render(<ParentComp />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>