I want to re-render my child ponent without re-rendering the parent ponent when the parent's state changes.
In this example, ponentWillReceiveProps 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);
}
ponentWillReceiveProps(nextProps) {
console.log('This Is Never Called');
}
render() {
return (
<View>
<Text>{this.props.myText}</Text>
</View>
);
}
}
I want to re-render my child ponent without re-rendering the parent ponent when the parent's state changes.
In this example, ponentWillReceiveProps 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);
}
ponentWillReceiveProps(nextProps) {
console.log('This Is Never Called');
}
render() {
return (
<View>
<Text>{this.props.myText}</Text>
</View>
);
}
}
Share
Improve this question
asked Sep 22, 2018 at 22:17
AstarAstar
2684 silver badges14 bronze badges
3
- What is the reasoning for that? – Estus Flask Commented Sep 22, 2018 at 22:33
- Trying to prevent unnecessary flickering when ponent is rendered. – Astar Commented Sep 22, 2018 at 23:33
- There won't be flickering if you're doing everything properly, the framework takes care of this. I'd expect the code you posted to work ok with ponent re-rendering. It's like the existing answer says, parent ponent should be re-rendered in order to re-render a child, and this is the way it's usually done. Any way, I posted an alternative just FYI. If you have real problems with flickering on rerenders, this is likely XY problem, I'd suggest to ask a new question and address the problem with flickering directly. – Estus Flask Commented Sep 23, 2018 at 0:15
2 Answers
Reset to default 4There 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.
In order to re-render child ponent with new props, parent ponent has to be re-rendered. There are generally no reasons to not re-render parent ponent 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 ponent re-render its children and make parent ponent 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 ponent 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.