react,redux store更新与memo、Pure组件、shouldUpdate
发布于 作者:苏南大叔 来源:程序如此灵动~大家都知道react
里面的context
功能和redux
是非常类似的,当redux
的store
里面的数据更新的时候,组件也会跟着更新。那么,这里有个疑问,如果碰到了使用memo
的组件,或者是PureComponent
,或者是shouldComponentUpdate
为false
的组件,或者是根本就没有使用到redux
但是被包裹在Prodiver
内部的组件。子组件会跟着redux
的store
数据更新而更新么?这就是本文要探讨的问题。
大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述redux
的store
数据更新是否会引起子组件更新的问题。测试环境:create-react-app@5.0.1
,node@16.14.2
,react@18.2.0
,react-dom@18.2.0
,react-redux@8.0.5
,@reduxjs/toolkit@1.9.0
。本文一句话总结就是:被redux
的Prodiver
包裹的子组件里面,数据变子组件就会被更新。但是目前有一个特例,就是:“shouldComponentUpdate:false”的组件。
本文对标文章:
https://newsn.net/say/react-context-update.html
前置内容
本文的正确理解,您可能需要下面的文章:
- 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/redux.html
- https://newsn.net/say/redux-2.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;
测试代码之组件部分
第一个测试组件:使用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
包裹的全部组件都更新了。即使是memo
、PureComponent
、甚至根本没有用的context
任何功能的组件。
【但是】【但是】【但是】【但是】【但是】shoudComponentUpdate
为false
的组件,可以阻止这个更新。这一点可能就是和context
更新引起子组件更新的不同之处。
【但是】【但是】【但是】【但是】【但是】
结束语
所以,本文的结论是:只要redux
的store
更新,内部包裹的组件除了“shouldComponentUpdate:false”的类式组件不会更新,其它任何组件都会更新。如果您知道如何作用某个组件不更新,可以留言给我。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。