useState не обновляет свое значение - PullRequest
2 голосов
/ 21 июня 2020

Я создаю форму ввода для электронной почты, и у меня отложено 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 ]

2 голосов
/ 21 июня 2020
Состояние

обновляется асинхронно, поэтому email не определено в первый раз, когда вы пытаетесь войти в него после обновления состояния.

Вы можете зарегистрировать электронную почту внутри useEffect хука, который будет вызван после изменения адреса электронной почты.

На следующем символе «12» e.target.value равно 12, а адрес электронной почты - 1

email равен 1, потому что когда событие onChange запускается в первый раз, email не было определено, но когда событие onChange запускается во второй раз, email уже было асинхронно обновлено до 1

2 голосов
/ 21 июня 2020

Разве это не ожидаемое поведение? 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>
    )
...