react,Context更新与memo组件、Pure组件、shouldUpdate
发布于 作者:苏南大叔 来源:程序如此灵动~大家都知道react
里面的context
功能非常好用,当context
里面的数据更新的时候,组件也会跟着更新。那么,这里有个疑问,如果碰到了使用memo
的组件,或者是PureComponent
,或者是shouldComponentUpdate
为false
的组件,或者是根本就没有使用到context
但是被包裹在Prodiver
内部的组件。子组件会跟着Context
更新而更新么?这就是本文要探讨的问题。
大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述上下文数据更新是否会引起子组件更新的问题。测试环境:create-react-app@5.0.1
,node@16.14.2
,react@18.2.0
,react-dom@18.2.0
。本文的结论就一句话:context
数据更新,所有相关子组件都会无条件更新重新渲染。(意思是你不看下面的内容也可以)
前置内容
本文的正确理解,您可能需要下面的文章:
- https://newsn.net/say/react-memo.html
- https://newsn.net/say/react-context.html
- https://newsn.net/say/react-pure-component.html
- https://newsn.net/say/react-usereducer-usecontext.html
- https://newsn.net/say/react-usecontext-usereducer.html
测试代码之基本部分
import React, { useState, createContext, PureComponent, useContext, memo, useRef } from "react";
const sunanContext = createContext(0);
const Sunan = () => {
const [status, setStatus] = useState("待更新");
return (
<div>
<p>测试Context是否会引起子组件更新<br />
Context内的值:{status}
<button onClick={() => setStatus("更新了")}>{"父组件更新"}</button><br />
</p>
<sunanContext.Provider value={status}>
<Sunan1 />
<Sunan2 />
<Sunan3 />
<Sunan4 />
<Sunan5 />
<Sunan6 />
<Sunan7 />
</sunanContext.Provider>
</div>
);
};
export default Sunan;
测试代码之组件部分
第一个测试组件:使用memo
的函数式组件。
function Sunan1_() {
const isMounted = useRef(null);
if (isMounted.current) {
console.log("sunan1 update")
} else {
isMounted.current = true;
}
const status = useContext(sunanContext);
return (
<>sunan1(memo)_: {status}<br /></>
)
}
const Sunan1 = memo(Sunan1_)
第二个测试组件:使用PureComponent
的类式组件。
class Sunan2 extends PureComponent {
constructor(props) {
super(props);
}
componentDidUpdate() {
console.log("Sunan2 update");
}
static contextType = sunanContext;
render() {
const status = this.context;
return (
<>Sunan2(pure)___: {status}<br /></>
)
}
}
第三个测试组件:使用shouldComponentUpdate
主动阻止更新的类式组件。
class Sunan3 extends React.Component {
constructor(props) {
super(props);
}
shouldComponentUpdate() {
return false;
}
componentDidUpdate() {
console.log("Sunan3 update");
}
static contextType = sunanContext;
render() {
const status = this.context;
return (
<>Sunan3(should:false) : {status}<br /></>
)
}
}
第四个测试组件:使用了useContext
普通函数式组件。
function Sunan4() {
const isMounted = useRef(null);
if (isMounted.current) {
console.log("Sunan4 update")
} else {
isMounted.current = true;
}
const status = useContext(sunanContext);
return (
<>sunan4(useContext)<br /></>
)
}
第五个测试组件:没使用任何Context
相关的普通函数式组件。
function Sunan5() {
const isMounted = useRef(null);
if (isMounted.current) {
console.log("Sunan5 update")
} else {
isMounted.current = true;
}
return (
<>sunan5(------)<br /></>
)
}
第六个测试组件:使用了Context
语句但没变量引用的普通类式组件。
class Sunan6 extends React.Component {
constructor(props) {
super(props);
}
componentDidUpdate() {
console.log("Sunan6 update");
}
static contextType = sunanContext;
render() {
return (
<>Sunan6(should:True) : <br /></>
)
}
}
第七个测试组件:没使用任何Context
的普通类式组件。
class Sunan7 extends React.Component {
constructor(props) {
super(props);
}
componentDidUpdate() {
console.log("Sunan7 update");
}
render() {
return (
<>Sunan7(------) <br /></>
)
}
}
测试结果
通过触发父组件里面的按钮,更新context
上下文,结果显示:Prodiver
包裹的全部组件都更新了。即使是memo
、PureComponent
、甚至shoudComponentUpdate
为false
的组件,甚至根本没有用的context
任何功能的组件。
结束语
所以,本文的结论是:只要context
更新,内部包裹的任何组件都会更新。如果您知道如何作用某个组件不更新,可以留言给我。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。