【问题标题】:React not triggering re-rendering of form inputs after state is updated via onChange通过 onChange 更新状态后,React 不会触发表单输入的重新呈现
【发布时间】:2021-05-28 20:09:50
【问题描述】:

我正在尝试构建一个验证码页面。

如果我为每个输入框创建一个单独的状态,然后使用下面的代码,它就可以正常工作。

<input type="number" value={inputOne} className={styles.codeInput} onChange={e => setInputOne(e.target.value}/>

但是,我试图将所有四个输入框的状态合并到一个状态对象中。

现在,当我输入一个数字时,它会移动到下一个输入,但它永远不会呈现该值。在开发工具中,我看到值会像更新一样闪烁,但它仍然保持为“value”而不是“value="1"”。

但是,如果我对我的代码做任何其他事情,例如更改 p 标签的文本,然后它会突然更新并且输入显示正确的值。

我只是想弄清楚我在这里做错了什么。

这是我当前的代码。

import { useState } from 'react'
import styles from '../../styles/SASS/login.module.scss'

export default function Verify(params) {
  const [verifCode, setVerifCode] = useState(['','','','']);

  const inputHandler = (e, index) => {
    // get event target value
    let value = e.target.value;
    // update state
    let newState = verifCode;
    newState[index] = value;
    setVerifCode(newState);
    // move focus to next input
    if (e.target.nextSibling) {
      e.target.nextSibling.focus()
    } else {
      // if at the last input, remove focus
      e.target.blur();
    }
  }

  return (
    <div className={styles.verify}>
      <p className={styles.title}>Verification</p>
      <p className={styles.message}>Please enter the verification code we sent to your email / mobile phone.</p>

      <div className={styles.form}>
        <input type="number" value={verifCode[0]} className={styles.codeInput} onChange={e => inputHandler(e, 0)}/>
        <input type="number" value={verifCode[1]} className={styles.codeInput} onChange={e => inputHandler(e, 1)}/>
        <input type="number" value={verifCode[2]} className={styles.codeInput} onChange={e => inputHandler(e, 2)}/>
        <input type="number" value={verifCode[3]} className={styles.codeInput} onChange={e => inputHandler(e, 3)}/>
      </div>

      <div className={styles.footer}>
        <button>Verify Code</button>
      </div>
    </div>
  )
};

【问题讨论】:

  • React 进行浅层比较以确定状态是否已更改,您的 setVerifCode 始终指向相同的引用,因此它们是相等的。
  • 啊。明白了。如果我在页面上编辑任何其他内容,知道为什么它似乎有效吗?试图了解理论上发生了什么。
  • 如果组件中的其他一些 not 浅相等的状态发生变化,它将触发更新,该更新将使用您在verifCode 中更改的状态进行渲染,甚至虽然 react 仍然不知道 verifCode 已经改变了。关键是 react 需要能够知道何时需要更新,这就是为什么您必须始终不可变地更新状态。

标签: javascript reactjs state use-state


【解决方案1】:

我认为问题出在以下代码

// update state
let newState = verifCode;
newState[index] = value;
setVerifCode(newState);

代码的第一行只是添加了一个指向值verifCode 的指针。 您修改了该数组中的一个元素,但newState 仍然是同一个变量verifCode。即使数组元素发生了本质上的变化,它仍然是相同的变量(相同的引用)。

尝试类似:

// update state
const newState = [...verifCode]; // create a copy of the old verifCode, creating new array 
newState[index] = value; // modify element
setVerifCode(newState); // set the new array to the state

【讨论】:

  • 这个答案是正确的,尽管我不确定它是否足够强调“永远不要尝试改变反应状态”这一点。被视为不可变的状态是 react 功能的核心,因为没有它,react 无法正确确定何时以及何时不触发组件更新。请参阅reactjs.org/docs/…(以及该部分上方的位)以获取文档中的启发性示例。
  • 参见reactjs.org/docs/update.html 获取更新更复杂状态对象的帮助
  • [...verifCode] 创建状态的副本,我们从不修改原始状态,这就是不变性的意义所在。除非我遗漏了一些东西@thisisrandy
  • @YungNoey 正如 Keith 在他的评论中提到的那样,该值设置为对内部状态做出反应,但由于参考未更新,因此不会重新渲染。您通过其他方式触发重新渲染可能会将新状态刷新到视图中。
  • @ssBarBee,我只是想确保 OP 清楚地理解,有这个不变性的概念对于反应的运作至关重要。您实际上并没有在答案中的任何地方说“不可变”,所以我试图将这个词汇添加到讨论中
猜你喜欢
  • 2016-11-09
  • 2021-10-10
  • 1970-01-01
  • 2020-04-13
  • 2019-04-05
  • 2021-01-12
  • 1970-01-01
  • 2019-05-07
  • 1970-01-01
相关资源
最近更新 更多