alchemist95
alchemist95

Reputation: 804

Have a Button to add same component in React

I am trying to implement a add button, clicking on which will render a component. Now that component fetches data once it mounts(call is made in componentDidMount()). In my implementation, even if i add a new component, even the old one gets mounted again which is not what i want.

This is my component

    class MyComponent extends React.Component{
        constructor(){
            super()
            this.state = {
                panels = []
            }
        }

        handleClick(event){
             const initialState = this.state.panels;
             this.setState({
                  panels: initialState.concat(<Panel key={initialState.length} />)
             )}
        }
        render(){
            return(
                 <div>
                 <button onClick={this.handleClick.bind(this)}>Add new</button>
                 {this.state.panels}
                 </div>
            )
        }
     }

Now, what happens is, whenever i add a new component, even the old one is mounted again and it starts fetching data that it already has fetched. How do I correct this? How do i dynamically add new components without bothering previously dynamically added components to the DOM without using ReactDOM.render() ?

Upvotes: 1

Views: 2864

Answers (2)

Davorin Ruševljan
Davorin Ruševljan

Reputation: 4392

You are trying to do it in non-react way. React way is to have render method that will display as many components, as described by state, be it 0,1,2... Then you add button will add one more element to state, and render will display all of them, and you do not need to worry about mounting components, and similar.

Upvotes: 0

CharlieBrown
CharlieBrown

Reputation: 4163

Don't store Component instances on your internal state, store the data you need to render it. With React is top-down, data to UI flow.

Let's suppose your Panel needs an id which for the sake of simplicity will be the index in the array. Change your code to the following:

class MyComponent extends React.Component{
        constructor(){
            super()
            this.state = {
                panels = []
            }
        }

        handleClick(event){
             const nextId = this.state.panels.length + 1
             this.setState({
                  panels: this.state.panels.concat([nextId])
             })
        }
        render(){
            return(
               <div>
                 <button onClick={this.handleClick.bind(this)}>Add new</button>
                 <div className='panel-wrapper'>
                  {
                    this.state.panels.map((panelId) => (
                      <Panel key={panelId} id={panelId} />
                    )
                  }
                  </div>
                 </div>
            )
        }
     }

By setting a key React will know which one is new and which already was there in the previous render. This is the React way, you update your data, and let your render function use that data at any given moment to represent your UI.

Hope it helps :)

Upvotes: 1

Related Questions