【问题标题】:How to avoid unnecessary re-renders in React?如何避免 React 中不必要的重新渲染?
【发布时间】:2020-11-22 10:13:28
【问题描述】:

我知道这个问题已被多次问过,但我试图了解当状态发生变化时做出反应渲染决策背后的逻辑以及我应该如何正确地写“反应”。

这是我的代码:

// Parent.js

import React, { useEffect, useState } from "react";
import ComponentA from "./ComponentA";
import ComponentB from "./ComponentB";

export default function App() {
  const [a, setA] = useState(false);
  const [b, setB] = useState(false);

  const onClickA = () => {
    setA((p) => !p);
  };

  const onClickB = () => {
    setB((p) => !p);
  };

  useEffect(() => {
    console.log("Parent rendered");
  });
  return (
    <div>
      <ComponentA value={a} onClick={onClickA} />
      <ComponentB value={b} onClick={onClickB} />
    </div>
  );
}
// Child A

import React, { useEffect } from "react";

export default function ComponentA(props) {
  useEffect(() => {
    console.log("A rendered");
  });

  return (
    <button onClick={props.onClick}>Button A - {props.value.toString()}</button>
  );
}
// Child B

import React, { useEffect } from "react";

export default function ComponentB(props) {
  useEffect(() => {
    console.log("B rendered");
  });

  return (
    <button onClick={props.onClick}>Button B - {props.value.toString()}</button>
  );
}

因此,当我单击按钮 A 或按钮 B 时,父组件将重新渲染,导致 ComponentA 和 ComponentB 都重新渲染,即使每个用户的 UI 与另一个的状态无关。我在想 react 会明白,如果我单击按钮 A,只会更改 a 状态变量,而 &lt;ComponentB /&gt; 不依赖于 a 状态,因此无需再次重新渲染它,因为它props 保持不变。所以我认为这段代码是错误的,应该以不同的风格编写,但我无法弄清楚。

显然,我认为既然a 不影响&lt;ComponentB /&gt;b 不影响&lt;ComponentA /&gt;,那我为什么不把状态分别传递给每个组件呢?这样,每个组件都将负责自己的重新渲染。但后来我想,如果将来 ComponentA 依赖于 bComponentB 依赖于 a 怎么办?每次我想共享状态时,我都无法更改代码,编写回调函数并将状态转换为道具,反之亦然。

有没有更好的方法可以提供这种灵活性而无需太多开销代码(ex redux)?

【问题讨论】:

    标签: reactjs dom rendering use-effect use-state


    【解决方案1】:

    这只是反应的关键概念。如果组件重新渲染,默认情况下所有子组件都将重新渲染。这不是问题,因为它通常非常快 - 除非您在渲染函数中进行昂贵的计算,否则您不应该这样做。

    有一些逃生舱口,例如 React.memoshouldComponentUpdate 类生命周期函数,但通常您不需要它们,而且过早的优化有时弊大于利。

    如果您遇到性能问题,请对其进行衡量,然后优化您发现的问题。否则,不要费力地重新渲染。

    【讨论】:

    • 由于计算成本高昂,我实际上很担心。为什么我不应该?我应该在哪里进行昂贵的计算?
    • 永远不要在渲染中,因为它可以在你不注意的情况下随时执行。在useMemo 中做类似的事情是可以的,因为这将限制重新计算类似事情的频率。否则在 useEffect 中 - 在渲染周期之外。
    猜你喜欢
    • 2021-12-25
    • 2020-07-26
    • 2020-01-10
    • 2020-12-21
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多