简体   繁体   中英

Render Only Child Component Only On Prop Change

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>
        );
    }
}

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM