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

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

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

大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述reduxstore数据更新是否会引起子组件更新的问题。测试环境:create-react-app@5.0.1node@16.14.2react@18.2.0react-dom@18.2.0react-redux@8.0.5@reduxjs/toolkit@1.9.0。本文一句话总结就是:被reduxProdiver包裹的子组件里面,数据变子组件就会被更新。但是目前有一个特例,就是:“shouldComponentUpdate:false”的组件。

本文对标文章:
https://newsn.net/say/react-context-update.html

前置内容

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

测试代码之基本部分

import React, { useState, useRef, memo, PureComponent, useEffect } from "react";
import { createStore } from 'redux';
import { Provider, useSelector } from 'react-redux';
import { connect } from 'react-redux';
const sunanStore = createStore((state = { sunan: { value: "未更新" } }, action) => {
    switch (action.type) {
        case 'sunan/setReduxValue':
            return { sunan: { value: action.value } }
        default:
            return state
    }
})
const Sunan = () => {
    const [status, setStatus] = useState("未更新");
    useEffect(() => {
        let status = sunanStore.getState().sunan.value;
        setStatus(status);
        sunanStore.subscribe(() => {
            let status = sunanStore.getState().sunan.value;
            setStatus(status);
        })
    }, []);
    const change = () => {
        sunanStore.dispatch({ type: 'sunan/setReduxValue', value: ("已更新") })
    }
    return (
        <div>
            <p>测试Redux是否会引起子组件更新</p>
            redux store内的值:{status} 
            <button onClick={() => change()}>{"点击按钮更新redux数据"}</button><br />
            <Provider store={sunanStore}>
                <Sunan1 />
                <Sunan2 />
                <Sunan3 />
                <Sunan4 />
                <Sunan5 />
                <Sunan6 />
                <Sunan7 />
            </Provider>
        </div>
    );
};
export default Sunan;

苏南大叔:react,redux store更新与memo、Pure组件、shouldUpdate - store定义
react,redux store更新与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 = useSelector((state) => state.sunan.value);
    return (
        <>sunan1(memo)_: {status}<br /></>
    )
}
const Sunan1 = memo(Sunan1_)

第二个测试组件:使用PureComponent的类式组件。

class Sunan2_ extends PureComponent {
    constructor(props) {
        super(props);
    }
    componentDidUpdate() {
        console.log("Sunan2 update");
    }
    render() {
        const status = this.props.sunan.value;
        return (
            <>Sunan2(pure)___: {status}<br /></>
        )
    }
}
const mapStateToProps = state => {
    return {
        sunan: state.sunan
    }
}
const Sunan2 = connect(mapStateToProps)(Sunan2_);

第三个测试组件:使用shouldComponentUpdate主动阻止更新的类式组件。【特例】【特例】【特例】

class Sunan3_ extends React.Component {
    constructor(props) {
        super(props);
    }
    shouldComponentUpdate(nextProps, nextState) {
        return false;
    }
    componentDidUpdate() {
        console.log("Sunan3 update");
    }
    render() {
        const status = this.props.sunan.value;
        return (
            <>Sunan3(should:false) : {status}<br /></>
        )
    }
}
const Sunan3 = connect(mapStateToProps)(Sunan3_);

第四个测试组件:使用了useSelector普通函数式组件。

function Sunan4() {
    const isMounted = useRef(null);
    if (isMounted.current) {
        console.log("sunan4 update")
    } else {
        isMounted.current = true;
    }
    const status = useSelector((state) => state.sunan.value);
    return (
        <>sunan4(useContext)<br /></>
    )
}

第五个测试组件:没使用任何Redux相关的普通函数式组件。

function Sunan5() {
    const isMounted = useRef(null);
    if (isMounted.current) {
        console.log("sunan5 update")
    } else {
        isMounted.current = true;
    }
    return (
        <>sunan5(---------)<br /></>
    )
}

第六个测试组件:使用了shouldComponentUpdate:true普通类式组件。

class Sunan6 extends React.Component {
    constructor(props) {
        super(props);
    }
    shouldComponentUpdate() {
        return true;
    }
    componentDidUpdate() {
        console.log("Sunan6 update");
    }
    render() {
        return (
            <>Sunan6(should:True) : <br /></>
        )
    }
}

第七个测试组件:没使用任何redux的普通类式组件(其实和第六个一样)。

class Sunan7 extends React.Component {
    constructor(props) {
        super(props);
    }
    componentDidUpdate() {
        console.log("Sunan7 update");
    }
    render() {
        return (
            <>Sunan7(------) <br /></>
        )
    }
}

测试结果

通过触发父组件里面的按钮,更新store内的数据,结果显示:Prodiver包裹的全部组件都更新了。即使是memoPureComponent、甚至根本没有用的context任何功能的组件。

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

【但是】【但是】【但是】【但是】【但是】
shoudComponentUpdatefalse的组件,可以阻止这个更新。这一点可能就是和context更新引起子组件更新的不同之处。
【但是】【但是】【但是】【但是】【但是】

结束语

所以,本文的结论是:只要reduxstore更新,内部包裹的组件除了“shouldComponentUpdate:false”的类式组件不会更新,其它任何组件都会更新。如果您知道如何作用某个组件不更新,可以留言给我。

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

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

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

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