Reactjs 如何避免React中不必要的重新渲染?
我知道这个问题已经被问过很多次了,但我试图理解当状态发生变化时,react呈现决策背后的逻辑,以及我应该如何正确地写“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
// 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>
);
}