1

I am working on a news feed web application and some of my code: MainContainer.js:

renderContent(source) {
        let content;
        switch (source) {
            case 'bbc':
            case 'cnn':
            case 'reuters':
                content = <Guide  source={source}/>;
                break;
            case 'medium':
                content=null;
                break;
            default:
                content = null;
                break;
        }

        return content;
    }
    render() {
        let {source} = this.props;
        return this.renderContent(source);

    }

This is code from MainContainer,which is a container component to render different news from CNN,or BBC. Its wrapper component is App

App.js render()

 <div>
      <ScrollableTab sources={sources} handleChange={this.handleSwitchTag.bind(this)} current={current}/>
      <MainContainer source={sources[current].toLowerCase()}/>
 </div> 

When a user click some tab in ScrollableTab,the source property of MainContainer changes,which will lead to a different Guide rendering.(After some logging,source did change in MainContainer).

However,this failed,Guide fail to umount. Only when user clicks Medium in which case renderContent()returns null can Guide umount.

I thought,this probably because React.js cannot distiguish similar components and with some optimization,it thinks there is no need to umount the 'same' component which actually is a different one.

So,I add key= in renderContent,I mean:

renderContent(source) {
        let content;
        switch (source) {
            case 'bbc':
            case 'cnn':
            case 'reuters':
                content = <Guide key={source} source={source}/>;
                break;
            case 'medium':
                content=null;
                break;
            default:
                content = null;
                break;
        }

        return content;
    }
    render() {
        let {source} = this.props;
        return this.renderContent(source);

    }

In this way, It works. But I cannot find any explanation in documentation of React.js. Or I just missed out some docs.Can someone tell me whether it is a bug or just over-optimization?

1

2 Answers 2

2

It's in the documentation of React, but this article from Tyler Mcginnis explains it.

The first thing React will do when setState is called is merge the object you passed into setState into the current state of the component. This will kick off a process called reconciliation. The end goal of reconciliation is to, in the most efficient way possible, update the UI based on this new state. To do this, React will construct a new tree of React elements (which you can think of as an object representation of your UI). Once it has this tree, in order to figure out how the UI should change in response to the new state, React will diff this new tree against the previous element tree.

Keys are what help React keep track of what items have changed, been added, or been removed from a list.

It’s important that each key be unique among siblings. We’ve talked a few times already about reconciliation and part of this reconciliation process is performing a diff of a new element tree with the most previous one. Keys make this process more efficient when dealing with lists because React can use the key on a child element to quickly know if an element is new or if it was just moved when comparing trees. And not only do keys make this process more efficient, but without keys, React can’t know which local state corresponds to which item on move. So never neglect keys when mapping.

You can find the complete article here React Interview Questions

Sign up to request clarification or add additional context in comments.

Comments

1

When you add key prop to the Guide component, it creates a new Guide component for each new source (getInitialState method should be called in this case), and will unmount the old component as it is no longer returned by the render function. However, when no key prop is present it updates the same component with a new prop( componentWillRecieveProp method should have been called in this case). The same Guide component is returned by the render method with a new prop and hence should not be unmounted.

3 Comments

Yes! This is how it works after some debugging. I need to fetch some data in Guide according to its props and stored in its state. I have two options.1. Add key prop like what I did in questions 2. Override componentWillReceiveProp in guide to update its state to force rerendering . Which way is better ?
I prefer the second way,because it will no cause mount and umount. Any suggestions?
I also prefer the second way, as this will cause re-rendering of the existing component. However, when using keys, it will require mounting new component and unmounting old component.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.