【问题标题】:(p)React avoid unnecessary rerender on submit(p)React 避免在提交时不必要的重新渲染
【发布时间】:2020-01-10 13:50:33
【问题描述】:

当焦点在输入框中时,按回车键提交表单。在提交时,错误会导致将错误插入到状态中,从而导致重新渲染并创建一个新元素来显示错误。

{error && <div>{error}</div>}

这会重新渲染整个不必要的组件。

肯定 (p)react 应该能够检测到只有新的错误元素被插入,而 DOM 的其余部分可以保持不变?

这样做的结果是我失去了输入的焦点,而且条纹 iframe 被重新安装。我怎样才能防止这种情况发生

DEMO

export default class App extends Component {
  state = { val: "Sample input", error: null };
  onSubmit = e => {
    e.preventDefault();
    this.setState({ error: "Some error" });
  };

  render(props, { val, error }) {
    return (
      <div>
        <h1>Example</h1>
        <form onSubmit={this.onSubmit}>
          {error && <div>{error}</div>}
          <div class="list">
            <input
              value={val}
              onChange={e => this.setState({ val: e.target.value })}
            />
            <button type="submit">Submit</button>
          </div>
        </form>
      </div>
    );
  }
}

⭐️更新

问题是how react reconciles children

解决方案 1 我可以通过向条件组件添加 key 属性来避免重新渲染整个组件并保持焦点。

{error && <div key='formError'>{error}</div>}

解决方案 2 或者,我可以将条件错误移到输入下方

<div class="list">
  <input
    value={val}
    onChange={e => this.setState({ val: e.target.value })}
  />
  <button type="submit">Submit</button>
</div>
{error && <div>{error}</div>}

解决方案3或者使用一个类来隐藏错误

<div className={error ? 'error' : 'hide'}>{error}</div>

【问题讨论】:

  • 你也没有从一开始就专注。你需要使用 refs 来做到这一点。

标签: reactjs preact


【解决方案1】:

您无法避免重新渲染,因为设置状态或道具更改将再次渲染组件。您可以使用 ref 再次聚焦元素。更新了您的示例代码。

Demo Link

【讨论】:

    【解决方案2】:

    最初你有&lt;div&gt;,里面有input。提交表单组件后需要显示两个&lt;div&gt;:一个代表错误,一个代表表单。但是要更新什么,要创建什么?如果没有 key 并且有 两个精确构造函数的元素,React 决定使用错误消息更新现有的(并删除表单)并创建一个将呈现表单的新元素。

    在这个动作中,它失去了在场内的焦点。所以这不是因为一般的重新渲染,而是因为reconciliation 特别是。

    是的,不错,key 通过建议 React 不要在divs 中搞乱,而是为错误消息创建新的来解决这个问题。如果您有不同的元素(例如,div 和...ul),您将永远不会体验到这一点。但提供key 也是处理该问题的合法方式。乍一看可能有点混乱。

    【讨论】:

    • 明白了,相同的标签让 React 搞砸了要更新什么和创建什么。
    • 正确,是对账算法。另一个解决方法是将错误 div 移到输入下方
    猜你喜欢
    • 1970-01-01
    • 2020-07-26
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    • 2016-07-17
    相关资源
    最近更新 更多