useState不会更新其值

时间:2020-06-21 09:40:10

标签: javascript reactjs react-hooks settimeout gatsby

我正在为电子邮件创建输入表单,并且在onChange上存在延迟,以致无法多次调用api。

这是我的代码:

const InformationCollection = (props) => {
  const [email, setEmail] = useState()
  const [collectedEmail, setCollectedEmail] = useState(1)

  useEffect(() => {
    let timeout = setTimeout(() => {
      setCollectedEmail(email)
      console.log(collectedEmail)
    }, 500)
    return () => {
      clearTimeout(timeout)
    }
  }, [email])

    return (
        <div className="form-group">
          <label htmlFor="inputmail">Email address</label>
          <input
            type="email"
            className="form-control"
            onChange={(e) => {
              setEmail(e.target.value)
              console.log(e.target.value + "this is what is set" + email)
            }}
            aria-label="Enter e-mail address"
          />
        </div>
    )
}

export default InformationCollection

在这一行上,如果我输入“ 1” console.log(e.target.value + "this is what is set" + email),则e.target.value为1,但email未定义。

在下一个字符“ 12”上,e.target.value为12但email为1

任何人都可以帮忙吗?

更新:

解决方案是使用2个useEffectHooks。一个用于格式为email的值,另一个用于延迟值collectedEmail

第二种解决方法是在第一个useEffect挂钩内进行抓取

const InformationCollection = (props) => {
  const [email, setEmail] = useState()
  const [collectedEmail, setCollectedEmail] = useState()

  useEffect(() => {
    let timeout = setTimeout(() => {
      //fetch directly here
      setCollectedEmail(email)
      console.log(collectedEmail)
    }, 500)
    return () => {
      clearTimeout(timeout)
    }
  }, [email])

  useEffect(() => {
    //fetch() here
    console.log(collectedEmail) //right value
  }, [collectedEmail])

    return (
        <div className="form-group">
          <label htmlFor="inputmail">Email address</label>
          <input
            type="email"
            className="form-control"
            onChange={(e) => {
              setEmail(e.target.value)
              console.log(e.target.value + "this is what is set" + email)
            }}
            aria-label="Enter e-mail address"
          />
        </div>
    )
}

export default InformationCollection

2 个答案:

答案 0 :(得分:2)

这不是预期的行为吗? email始终是onChange处理程序内部进行更改之前的值。因为还没有发生重新渲染。

要查看呈现的值,请执行以下操作:

    return (
        <div className="form-group">
          <label htmlFor="inputmail">Email address: { email }</label>
          <input
            type="email"
            className="form-control"
            onChange={(e) => {
              setEmail(e.target.value)
              console.log(e.target.value + "this is what is set" + email)
            }}
            aria-label="Enter e-mail address"
          />
        </div>
    )

答案 1 :(得分:2)

状态是异步更新的,这就是为什么在更新状态后第一次尝试记录email时未定义它的原因。

您可以将电子邮件记录在useEffect挂钩中,该电子邮件在更改后将被调用。

在下一个字符“ 12”上,e.target.value为12,电子邮件为1

email1,因为第一次触发onChange事件时,email是未定义的,而第二次触发onChange事件时,{ {1}}已异步更新为email