Reputation: 9113
I'm trying to learn and test React.PureComponent and it keeps rendering even though no state changes for that pure component.
My PureComponent is very simple and it accepts only one Redux Action function via connect
hoc
import React from 'react';
import {
Container,
Button
} from 'reactstrap'
import { connect } from 'react-redux'
import { resetWorkouts } from '../actions/workoutApiActions'
class About extends React.PureComponent {
render () {
const { resetWorkouts } = this.props;
console.log('in about render...')
return (
<React.Fragment>
<Container>
<h2>Api Data Reset</h2>
<Button color="danger" onClick={resetWorkouts}>Reset Data</Button>
</Container>
</React.Fragment>
);
}
}
const mapDispatchToProps = dispatch => {
return {
resetWorkouts: () => dispatch(resetWorkouts())
}
}
export default connect(null, mapDispatchToProps)(About);
In the above code, you can see that, there is no state in the component. It only accepts the action function as props
from connect
. However, whenever I clicks on the Reset Data
button, it keeps calling the render
method as shown in the screenshot.
In the screenshot, I can see that, global state store has been changed whenever, I click a button. But, that state is not used in my PureComponent and it should be out of the scope and my component should ignore to re-render.
Or Redux Action functions are created every time the global state store has been changed. And passed as a new object to my PureComponent ?
Theoretically, I don't need to write my own shouldComponentUpdate
function, right? I'm confused and could you please help me to understand about this behaviour?
My goal is I don't want my PureComponent to render again when a user clicks a button.
Updates:
I have tried like the following according to this article and it's still re-rendering
const mapDispatchToProps = {
resetWorkouts
};
Upvotes: 0
Views: 1568
Reputation: 649
this because react do a shallow comparison between the prevProps and the nextProps,
and you can control that only in the shouldComponentUpdate
, react doesn't know that the dispatcher is the same one from the previous render, because you are using return inside the mapDispatchToProps
function.
In your component and in your case, while the function will remain the same, you can go with two paths:
path 1:
override the shouldComponentUpdate
life cycle hook, to be as the following:
shouldComponentUpdate(){
return false;
}
path 2:
get rid of the return inside mapDispatchToProps
and simplify the connect so it be as the following:
`conncect(state => ({}), {
resetWorkouts: resetWorkouts})(YourComponent);`
using one of the above paths should make you good to go
Upvotes: 3
Reputation: 731
The reason why your component is rendering is because everytime the following function executes:
const mapDispatchToProps = dispatch => {
return {
resetWorkouts: () => dispatch(resetWorkouts())
}
}
your components receives a new instance of a property named resetWorkouts
(because you're creating an inline array function). You may look at the ownProps
to check if your component already have the resetWorkouts
:
const mapDispatchToProps = (dispatch, ownProps) => {
return {
resetWorkouts: ownProps.resetWorkouts || () => dispatch(resetWorkouts())
}
}
Upvotes: 1