如何避免在无状态组件中使用基于 React class 的组件作为父组件进行不必要的更新
How to avoid unnecesary update in a stateless component with a React class-based component as a parent
我正在学习 React 并且我发现 React.memo() "is not working",因为我的组件再次重新呈现我在父 class 上所做的每次更新零件。但问题是组件上的道具不会改变,至少对我来说是有意义的
我使用 useEffect 钩子在重新渲染的屏幕上打印,尽管我使用 React.memo(Men)
const Men = props => {
useEffect(() => {
console.log("rendered");
});
return <p onClick={props.add}>{props.adder}</p>;
};
React.memo(Men);
class App extends React.Component {
state = {
counter: 0,
adder: "press"
};
add = () => {
this.setState(prevState => {
return {
counter: prevState.counter + 1
};
});
};
render() {
return (
<div className="App">
<p>{this.state.counter}</p>
<Men adder={this.state.adder} add={this.add} />
</div>
);
}
}
我希望在我的控制台中,useEffect 挂钩中的消息 'rendered' 只出现一次。
React 钩子也有一个依赖数组,没有它 useEffect 钩子将在每次渲染时触发它的效果。 react hooks reference
useEffect(() => {
console.log("rendered");
}); // every render
useEffect(() => {
console.log("rendered");
}, []); // on mount, once
useEffect(() => {
console.log("rendered");
}, [propValue]); // every time propValue is a new reference
memo
HOC 函数还可以采用相等比较函数来进一步测试何时应该重新渲染,但请注意,React 仍然控制它们何时发生。 HOC(高阶组件)包装一个组件和 return 一个要渲染的新组件。您包装了您的组件,但不保存 returned 值以供稍后呈现。
const MemoizedComponent = React.memo(Component, [optional prop compare function]);
...
render() {
return (
<MemoizedComponent />
);
};
发生这种情况是因为您使用 memo
的方式 - 您需要使用 React.memo(Men)
给您的 return 值。
像这样:
This CodePen will cause a re-render
This CodePen will NOT cause a re-render
正确:
const MenBefore = props => {
React.useEffect(() => {
console.log("rendered");
});
return <p onClick={props.add}>{props.adder}</p>;
};
////////////////////////////////////////
const Men = React.memo(MenBefore); // <--- THIS LINE
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class App extends React.Component {
state = {
counter: 0,
adder: "Click Me - I will -NOT- cause a re-render"
};
add = _ => {
this.setState(prevState => {
return {
counter: prevState.counter + 1
};
});
};
render() {
return (
<div className="App">
<p>{this.state.counter}</p>
<Men adder={this.state.adder} add={this.add} />
</div>
);
}
}
ReactDOM.render(<App />, document.body);
不正确:
const Men = props => {
React.useEffect(() => {
console.log("rendered");
});
return <p onClick={props.add}>{props.adder}</p>;
};
/////////////////////////////
React.memo(Men); // <<<--------- WRONG
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
class App extends React.Component {
state = {
counter: 0,
adder: "Click Me - I will cause a re-render"
};
add = _ => {
this.setState(prevState => {
return {
counter: prevState.counter + 1
};
});
};
render() {
return (
<div className="App">
<p>{this.state.counter}</p>
<Men adder={this.state.adder} add={this.add} />
</div>
);
}
}
ReactDOM.render(<App />, document.body);
我正在学习 React 并且我发现 React.memo() "is not working",因为我的组件再次重新呈现我在父 class 上所做的每次更新零件。但问题是组件上的道具不会改变,至少对我来说是有意义的
我使用 useEffect 钩子在重新渲染的屏幕上打印,尽管我使用 React.memo(Men)
const Men = props => {
useEffect(() => {
console.log("rendered");
});
return <p onClick={props.add}>{props.adder}</p>;
};
React.memo(Men);
class App extends React.Component {
state = {
counter: 0,
adder: "press"
};
add = () => {
this.setState(prevState => {
return {
counter: prevState.counter + 1
};
});
};
render() {
return (
<div className="App">
<p>{this.state.counter}</p>
<Men adder={this.state.adder} add={this.add} />
</div>
);
}
}
我希望在我的控制台中,useEffect 挂钩中的消息 'rendered' 只出现一次。
React 钩子也有一个依赖数组,没有它 useEffect 钩子将在每次渲染时触发它的效果。 react hooks reference
useEffect(() => {
console.log("rendered");
}); // every render
useEffect(() => {
console.log("rendered");
}, []); // on mount, once
useEffect(() => {
console.log("rendered");
}, [propValue]); // every time propValue is a new reference
memo
HOC 函数还可以采用相等比较函数来进一步测试何时应该重新渲染,但请注意,React 仍然控制它们何时发生。 HOC(高阶组件)包装一个组件和 return 一个要渲染的新组件。您包装了您的组件,但不保存 returned 值以供稍后呈现。
const MemoizedComponent = React.memo(Component, [optional prop compare function]);
...
render() {
return (
<MemoizedComponent />
);
};
发生这种情况是因为您使用 memo
的方式 - 您需要使用 React.memo(Men)
给您的 return 值。
像这样:
This CodePen will cause a re-render
This CodePen will NOT cause a re-render
正确:
const MenBefore = props => {
React.useEffect(() => {
console.log("rendered");
});
return <p onClick={props.add}>{props.adder}</p>;
};
////////////////////////////////////////
const Men = React.memo(MenBefore); // <--- THIS LINE
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class App extends React.Component {
state = {
counter: 0,
adder: "Click Me - I will -NOT- cause a re-render"
};
add = _ => {
this.setState(prevState => {
return {
counter: prevState.counter + 1
};
});
};
render() {
return (
<div className="App">
<p>{this.state.counter}</p>
<Men adder={this.state.adder} add={this.add} />
</div>
);
}
}
ReactDOM.render(<App />, document.body);
不正确:
const Men = props => {
React.useEffect(() => {
console.log("rendered");
});
return <p onClick={props.add}>{props.adder}</p>;
};
/////////////////////////////
React.memo(Men); // <<<--------- WRONG
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
class App extends React.Component {
state = {
counter: 0,
adder: "Click Me - I will cause a re-render"
};
add = _ => {
this.setState(prevState => {
return {
counter: prevState.counter + 1
};
});
};
render() {
return (
<div className="App">
<p>{this.state.counter}</p>
<Men adder={this.state.adder} add={this.add} />
</div>
);
}
}
ReactDOM.render(<App />, document.body);