I. What
I had such question when I first join my current company. We use react-redux
lib, and let redux
to manage nearly all data in frontend.
- [Fact 1]: We all know that the parent re-render will trigger children component re-render by default (if no
shouldComponentUpdate
provided in child component, it will always default totrue
). This way, it might introduce unnecessary re-render for children component even though it should NOT. [Fact 2]: Redux creating HoC Pure component for its corresponding UI components. That is, container components actually inherit
PureComponent
(by default, it implementsshouldComponentUpdate
and returnfalse
ifprops
andstate
stay the same). Thus, there is no need we use pure components for the UI components, as its container components already handle it[Question]: Does that means we don’t need
PureComponent
inRedux
project? ——>NO
II. Why?
- Actually, Redux uses
connect()
to create HoC Pure component, which actually inheritsPureComponent
(by default, it implementsshouldComponentUpdate
and returnfalse
ifprops
andstate
stay the same). All UI components now hide behind the Container components, which arePure.Components
- But, we cannot guarantee all the components have a corresponding container components created by redux. Still, there exist react component not plugging into redux store. In this case, it will trigger child component re-render if the parent component re-render
- So, we still need to inherit
PureComponent
in some case in redux project
III. Code
Play with part_1 and part_2, to see when:
child plugging into redux;
child not plugging into redux;
child not plugging into redux, but with
shouldComponentUpdate()
App.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import { Provider } from "react-redux";
import React from "react";
import ReactDOM from "react-dom";
import Parent from "./Parent";
import store from "./store";
class App extends React.Component {
render() {
return (
<Provider store={store}>
<div className="App">
<Parent />
</div>
</Provider>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);Parent.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35import { connect } from "react-redux";
import React from "react";
import Child from "./Child";
let cnt_parent = 0;
class Parent extends React.Component {
constructor() {
super();
this.state = {
parentStr: "This is parent String"
};
}
clickHandler = () => {
this.setState({
parentStr: "Parent String changed!"
});
};
render() {
console.log("parent cnt: ", cnt_parent++);
return (
<div
onClick={() => {
this.clickHandler();
}}
>
{this.state.parentStr}
<Child />
</div>
);
}
}
export default Parent;Child.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33import React from "react";
import { connect } from "react-redux";
let cnt_child = 0;
class Child extends React.Component {
static defaultProps = { childStr: "This is child String" };
/*
// Part_1
shouldComponentUpdate() {
return false;
}
*/
render() {
console.log("child cnt: ", cnt_child++);
return <div>{this.props.childStr}</div>;
}
}
/*
// Part_2
const mapStateToProps = state => ({
childStr: state.child
});
const mapDispatchToProps = dispatch => {};
export default connect(
mapStateToProps,
null
)(Child);
*/
export default Child;