Reputation: 268
I want to re-render my child component without re-rendering the parent component when the parent's state changes.
In this example, componentWillReceiveProps is never called.
Thank You!
Parent Component
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
myValue: 'hello'
}
}
shouldComponentUpdate(nextProps, nextState) {
return false;
}
myFunction() {
this.setState(prevState => {
return {myValue: 'world'};
});
}
render() {
return (
<View>
<Button onPress={myFunction} title="Learn More"/>
<Child myText={this.state.myValue}/>
</View>
);
}
}
Child Component
export default class Child extends Component {
constructor(props) {
super(props);
}
componentWillReceiveProps(nextProps) {
console.log('This Is Never Called');
}
render() {
return (
<View>
<Text>{this.props.myText}</Text>
</View>
);
}
}
Upvotes: 2
Views: 4413
Reputation: 222603
In order to re-render child component with new props, parent component has to be re-rendered. There are generally no reasons to not re-render parent component in this situation. React was designed to do this efficiently and reuse existing DOM elements on re-render where possible.
The alternative approach is to make child component re-render its children and make parent component trigger the update somehow. This can be done with refs, for instance:
export default class Parent extends Component {
state = {
myValue: 'hello'
}
childRef = React.createRef();
myFunction = () => {
this.childRef.current.setText('world');
}
render() {
return (
<View>
<Button onPress={this.myFunction} title="Learn More"/>
<Child ref={this.childRef} myText={this.state.myValue}/>
</View>
);
}
}
And child component maintains its own state:
export default class Child extends Component {
static getDerivedStateFromProps({ myText }, state) {
return {myText, ...state};
}
setText(myText) {
this.setState({ myText });
}
render() {
return (
<View>
<Text>{this.state.myText}</Text>
</View>
);
}
}
Here's a demo.
This is acceptable solution but it results in less straightforward design. 'Dumb' Child
like in original code is a preferable way to do this which shouldn't be changed for optimization reasons in general. If there are problems with re-rendering Parent
children, they possibly should be addressed in another way.
Upvotes: 2
Reputation: 15692
There is no way to do what you are proposing explicitly. When you define:
shouldComponentUpdate(nextProps, nextState) {
return false;
}
are telling Parent
never to rerender after its initial render. However the passing of props to Child
(and therefore the impetus for Child
to rerender) happens inside the render
method of Parent
. So when you block rerending on Parent
you are also blocking rerendering on all children of Parent
.
There is, however, no need to block rerendering on Parent
because React will modify the DOM as little as possible, so you will only see changes in parts of parent that need to be modified (due to a change of state). As long as all the props being passed to the other children of Parent
(other than Child
that is) remain unchanged, only Child
will be modified in a Parent.render
call.
Basically React already handles what you are trying to do.
Upvotes: 4