组件本地状态不使用react自定义钩子更新

IT技术 javascript reactjs react-hooks
2021-04-29 16:40:11

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

我的自定义钩子:

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

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

有效真
错误无效
有效假
错误发现一些错误

相反,我看到的是:

有效真
错误空
有效真
错误空

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

1个回答

使用钩子更新状态就像setState在类组件中一样是异步的,并且由于状态没有发生变化,contentIsValid并且contentError仍然会引用陈旧的旧状态而不是新状态。

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

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>