Reactjs 如何避免React中不必要的重新渲染?

Reactjs 如何避免React中不必要的重新渲染?,reactjs,dom,rendering,use-effect,use-state,Reactjs,Dom,Rendering,Use Effect,Use State,我知道这个问题已经被问过很多次了,但我试图理解当状态发生变化时,react呈现决策背后的逻辑,以及我应该如何正确地写“react” 这是我的代码: // Parent.js import React, { useEffect, useState } from "react"; import ComponentA from "./ComponentA"; import ComponentB from "./ComponentB"; e

我知道这个问题已经被问过很多次了,但我试图理解当状态发生变化时,react呈现决策背后的逻辑,以及我应该如何正确地写“react”

这是我的代码:

// 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>
  );
}
//Parent.js
从“React”导入React,{useffect,useState};
从“/ComponentA”导入组件A;
从“/ComponentB”导入组件B;
导出默认函数App(){
const[a,setA]=useState(false);
const[b,setB]=useState(false);
const onclick=()=>{
刚毛((p)=>!p);
};
const onClickB=()=>{
挫折((p)=>!p);
};
useffect(()=>{
console.log(“父级渲染”);
});
返回(
);
}
//子对象A
从“React”导入React,{useffect};
导出默认功能组件A(道具){
useffect(()=>{
console.log(“已呈现”);
});
返回(
按钮A-{props.value.toString()}
);
}
//子B
从“React”导入React,{useffect};
导出默认功能组件B(道具){
useffect(()=>{
控制台日志(“B呈现”);
});
返回(
按钮B-{props.value.toString()}
);
}
因此,当我单击按钮A或按钮B时,父组件将重新呈现,导致组件A和组件B都重新呈现,即使它们各自的UI与另一个的状态无关。我想react会理解,如果我单击按钮A,只有
A
状态变量会更改,
不依赖于
A
状态,因此无需再次重新渲染,因为它的
道具保持不变。所以我认为这段代码是错误的,应该以不同的风格编写,但我无法理解这一点

显然,我认为既然
a
不影响
b
不影响
,那么为什么我不将状态分别传递给每个组件呢?这样,每个组件将负责自己的重新渲染。但是后来我想,如果将来
组件a
依赖于
b
或者
组件b
依赖于
a
?我不能每次想要共享状态、编写回调函数、将状态转换为道具时都更改代码,反之亦然


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

这正是react的关键概念。如果组件重新渲染,默认情况下,所有子级都将重新渲染。这不是一个问题,因为它通常非常快-除非在渲染函数中进行昂贵的计算,而这是不应该的

有一些逃生舱口,如
React.memo
shouldComponentUpdate
类生命周期函数,但通常您不需要它们,过早的优化往往弊大于利


如果您有性能问题,请对其进行测量,然后优化您发现的问题。否则,不要过分担心重播。

由于计算量大,我实际上很担心。为什么我不应该?我应该在哪里进行昂贵的计算呢?千万不要在渲染中进行,因为渲染可以在任何时候执行,而你永远不会注意到。在
usemo
中执行类似操作是可以的,因为这样会限制重新计算类似内容的频率。否则在useEffect中-在渲染周期之外。
// 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>
  );
}