最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Render Only Child Component Only On Prop Change - Stack Overflow

programmeradmin0浏览0评论

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
Add a ment  | 

2 Answers 2

Reset to default 4

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 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.

发布评论

评论列表(0)

  1. 暂无评论