【问题标题】:React functional component does not change as soon as value changesReact 功能组件不会随着值的变化而改变
【发布时间】:2020-04-12 15:06:24
【问题描述】:

我已经为重置密码页面制作了一个反应组件。重置令牌发送到用户邮箱后,重置页面有三个输入:令牌、新密码和确认密码。后两者被隐藏,直到在令牌字段中输入sha256 token,密码字段出现,令牌字段消失。这曾经有效,直到我还在重置 URL 中转发了带有重置令牌的 URL。因此,我必须在我的useEffect() 中添加compShow() 函数,以便在加载组件后立即检查令牌并更新令牌字段,使其不可见。这适用于带有重置令牌的 URL,但没有重置的 URL 应该首先仅显示令牌字段,然后隐藏令牌并显示密码字段现在无法按预期工作。只有在输入令牌后按一个额外的字符(我使用 空格),令牌字段才会消失。我认为这是因为我第一次在onChangedHandler 函数中更改placeholder 状态变量的值时,compShow() 不会被触发。但是当我添加一个额外的字符时,compShow 函数会检测到placeholder 的变化并执行其各自的代码。

谁能告诉我为什么会发生这种情况以及我应该怎么做才能得到预期的结果?

下面提供代码sn-p

const [placeholder, setPlaceholder] = useState('')

const { onReleaseError, onError } = props

const compShow = useCallback(() => {
    if (validator.isHash(placeholder, 'sha256')) {
      setShowToken({ display: 'none' })
      setShow(style.show)
      setErrorType('red')
      onReleaseError()
    }
  }, [placeholder, onReleaseError])

  useEffect(() => {
    const path = new URL(document.location).pathname.split('/')[2] || null
    if (path) {
      setPlaceholder(path)
      compShow()
    } else {
      setErr(onError)
      if (onError) setErrorType('green')
    }
  }, [compShow, onError])

  const onChangeHandler = e => {
    setPlaceholder(e.target.value)
    compShow()
  }

【问题讨论】:

  • 这个问题已经回答过几次了。请参考:stackoverflow.com/questions/53845595/…
  • 这里有一半的变量是未定义的,能否请您创建一个minimal, reproducible example
  • 我唯一可以说compShow 不会因为被调用而改变。另一方面,如果onError是在没有useCallback的父组件中创建的函数,则每次重新渲染父组件时都会更改,触发useEffect。另外,compShow 会在每次placeholder 发生变化时发生变化,因此依赖关系之间存在潜在的无限循环..
  • @Aprillion onError 是在前一个(兄弟)组件中更改的 redux 状态变量,只是为了通知令牌已发送到邮件并且应该在输入有效的重置令牌后立即失效.它可能会在其值更改后重新渲染useEffect()。有什么办法摆脱它吗?
  • @Thanh-QuyNguyen 感谢 mahn。将调查 useRefs。

标签: javascript reactjs ecmascript-6 react-hooks usecallback


【解决方案1】:

显然解决方案要简单得多。 useCallback 锁定它在组件渲染/更新开始时采用的值。在组件开头定义的placeholder 是一个空字符串,因此在我们调用compShow 函数时它不会改变。但是当我接受一个可能是也可能不是 placeholder 但具有相同值的输入时,compShow 函数采用 placeholder 的更新值并按预期​​运行。

const [placeholder, setPlaceholder] = useState('')
const { onReleaseError, onError } = props

const compShow = useCallback(
    val => {
      if (validator.isHash(val, 'sha256')) {
        setShowToken({ display: 'none' })
        setShow(style.show)
        setErrorType('red')
        onReleaseError()
      }
    },
    [onReleaseError]
  )

  useEffect(() => {
    const path = new URL(document.location).pathname.split('/')[2] || null
    if (path) {
      setPlaceholder(path)
      compShow(path)
    } else {
      setErr(onError)
      if (onError) setErrorType('green')
    }
  }, [compShow, onError])

  const onChangeHandler = e => {
    setPlaceholder(e.target.value)
    compShow(e.target.value)
  }

【讨论】:

  • 不错的解决方案,但请注意解释与useCallback无关。 placeholder 是一个常量值,调用 setPlaceholder 不会修改变量,它只会触发新的渲染,并且同一函数的不同执行将使用新值创建不同的常量(也称为占位符)。在 useCallback 或其他闭包中也使用了相同的值。如果您需要使用未来值而不是当前值,那么您的解决方案将在这里完美运行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 1970-01-01
  • 2023-03-08
相关资源
最近更新 更多