我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

大家都知道react里面的context功能非常好用,当context里面的数据更新的时候,组件也会跟着更新。那么,这里有个疑问,如果碰到了使用memo的组件,或者是PureComponent,或者是shouldComponentUpdatefalse的组件,或者是根本就没有使用到context但是被包裹在Prodiver内部的组件。子组件会跟着Context更新而更新么?这就是本文要探讨的问题。

苏南大叔:react,Context更新与memo组件、Pure组件、shouldUpdate - context-component-update
react,Context更新与memo组件、Pure组件、shouldUpdate(图3-1)

大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述上下文数据更新是否会引起子组件更新的问题。测试环境:create-react-app@5.0.1node@16.14.2react@18.2.0react-dom@18.2.0。本文的结论就一句话:context数据更新,所有相关子组件都会无条件更新重新渲染。(意思是你不看下面的内容也可以)

前置内容

本文的正确理解,您可能需要下面的文章:

测试代码之基本部分

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;

苏南大叔:react,Context更新与memo组件、Pure组件、shouldUpdate - 包裹组件
react,Context更新与memo组件、Pure组件、shouldUpdate(图3-2)

测试代码之组件部分

第一个测试组件:使用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包裹的全部组件都更新了。即使是memoPureComponent、甚至shoudComponentUpdatefalse的组件,甚至根本没有用的context任何功能的组件。

苏南大叔:react,Context更新与memo组件、Pure组件、shouldUpdate - 测试结果
react,Context更新与memo组件、Pure组件、shouldUpdate(图3-3)

结束语

所以,本文的结论是:只要context更新,内部包裹的任何组件都会更新。如果您知道如何作用某个组件不更新,可以留言给我。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react