Collin
Collin

Reputation: 419

Update component state by onClick of parent component

My goal in the app is, that when button is clicked, the action is set to new and given to the child component. As soon as the child component receives this value, it should show the text from the div. At further implementation, I will add another button, on click of this button, it will set the action to edit. The child component should recieve the value automatically and based on this, returns another div.

let actionToPerform = "";

    function actionState(action){
       if(action === 'new'){
           actionToPerform = 'new'
       }else{
           actionToPerform = 'edit'
       }
    }

 <button onClick={() => actionState('new')}>Create new Shoppinglist</button>
 <button onClick={() => actionState('edit')}>Edit Shoppinglist</button>
 <Edit action={actionToPerform}/>

Child component:

export default class Edit extends React.Component {


    constructor(props){
        super(props);
        this.state = {actionToPerform: this.props.action}
    }

    

    showTitle() {
        if(this.state.actionToPerform === 'new'){
            return <div>new Shoppinglist</div>
        }else if(this.state.actionToPerform === 'edit'){
            return <div>edit</div>
        }else{
            return <div>nothing to show</div>
        }
    }



   render() {
       return (
           this.showTitle()
       )
   }
}

I know I should work somehow with componentDidMount and componentUpdate to fulfill this, but was not able to do it. Right now, at loading page, it triggers the onClick action, I don't know why. When I click on the button, nothing else happens

Upvotes: 1

Views: 190

Answers (2)

Taki
Taki

Reputation: 17664

Parent component :

When you update the actionToPerform your component doesn't know that and it will not re-render, you need to keep it in its state :

state = {
  actionToPerform: ""
}

updateState(actionToPerform){
    this.setState({ actionToPerform })
}

<button onClick={() => this.updateState('new')}>Create new Shoppinglist</button>
<button onClick={() => this.updateState('edit')}>Edit Shoppinglist</button>
<Edit action={actionToPerform}/>

now when you click on one of the buttons, the state's value updates and the component re-renders, passing the new value to the child.

Child component :

You shouldn't set the initial value of the state from the props , see Anti-pattern: Unconditionally copying props to state

And you can even remove it all together because you can do conditional rendering depending the props value :

export default class Edit extends React.Component {
  render() {
    return this.props.actionToPerform === "new" ? (
      <div>new Shoppinglist</div>
    ) : this.props.actionToPerform === "edit" ? (
      <div>edit</div>
    ) : (
      <div>nothing to show</div>
    );
  }
}

Upvotes: 1

Prakash Sharma
Prakash Sharma

Reputation: 16482

Instead of using state in Edit component, you should use the state in parentt component and pass that state to child (Edit) component as prop and use that.

parent.js

actionState = (action) => {
   if(action === 'new'){
      this.setState({ actionToPerform: 'new' })
   } else{
      this.setState({ actionToPerform: 'edit' })
   }
}
render() {
 return (
   <div>
     <button onClick={() => this.actionState('new')}>Create new Shoppinglist</button>
     <button onClick={() => this.actionState('edit')}>Edit Shoppinglist</button>
     <Edit action={this.state.actionToPerform}/>
   </div>
 )
}

child.js

export default class Edit extends React.Component {

    showTitle() {
        if(this.props.actionToPerform === 'new'){
            return <div>new Shoppinglist</div>
        } else if(this.props.actionToPerform === 'edit'){
            return <div>edit</div>
        } else{
            return <div>nothing to show</div>
        }
    }

   render() {
       return (
           this.showTitle()
       )
   }

Upvotes: 0

Related Questions