0

This is the code from the parent:

_handleSelectedTodo(e) {
  e.preventDefault(); 
  this.setState({checkedIds: [...this.state.checkedIds, e.target.value]});
}
// render () { ...
<ul>
{todos.map((todo,todoIndex) => // The map method has default argument on second index, the index of the current todo in map execution. We use it so we do not have to use findIndex when we need to dispatch action that needs index of a specific todo
  <Todo
    key={todo.id}
    {...todo} // pass all the todo property
    onClick={() => onTodoClick(todo.id)}
    onTrashClick={() => onDeleteClick(todoIndex)}
    handleSelectedTodo = {this._handleSelectedTodo}
    checked={Boolean(this.state.checkedIds.includes(todo.id))}
  />
)}

This is what I tried since assigning props on checkbox doesn't update on the Child Todo code, checked can be true or false that will depend on props:

componentWillMount() {
  this.setState({ checked: this.props.checked })
}
// render() { ...
<input
  checked={this.state.checked}
  onChange={handleSelectedTodo}
  type="checkbox"
  value={id}
></input>

Checking on the checkbox updates the parent component state but the checkbox on child is not checked. help?

2 Answers 2

1

This code can also be written this way:-

_handleSelectedTodo(e) {
  e.preventDefault(); 
  this.setState({checkedIds: [...this.state.checkedIds, e.target.value]});
}
render () { ...
<ul>
{todos.map((todo,todoIndex) => {
  let isChecked = (this.state.checkedIds.indexOf(todo.id) >= 0);
  return (
     <Todo
       key={todo.id}
       {...todo} // pass all the todo property
       onClick={(id) => onTodoClick(todo.id)} //This event should be binded to 'this' inside the constructor
       onTrashClick={(todoIndex) => onDeleteClick(todoIndex)}
       handleSelectedTodo = {this._handleSelectedTodo}
       checked={isChecked}
     />
  )
 });
}

This child component should depend on it's parent state for it's checked property

<input
  checked={this.props.checked}
  onChange={handleSelectedTodo}
  type="checkbox"
  value={id}
></input>

If you want to keep the checked property of child as a state of child as well, then what Mayank said about componentWillReceiveProps would be the right approach.

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

5 Comments

I did it inside the Todo Component, it doesnt work: checked={ Boolean(this.state.checkedIds.indexOf(todo.id) >= 0) ? true : false }
Just this should work. No need for Boolean let isChecked = (this.state.checkedIds.indexOf(todo.id) >= 0);
as much as I want to say it does, It don't :/
Would you like to screen share through team viewer, I can then better debug this?
when I click the checkboxes, the last one checked will be checked but not the latest one.
1

Reason is, componentWillMount will get called only before the initial rendering not after that, when you are updating the state of parent component, state of child component is not getting updated.

Use componentWillReceiveProps method to update the state of child component:

componentWillReceiveProps(nextProps){
   if(nextProps.checked != this.state.checked)
        this.setState({checked: nextProps.checked})
}

Or simplest solution will be don't save the value in state of child component, directly use the props values, Like this:

<input
    checked={this.props.checked}      //here use this.props.checked directly
    onChange={handleSelectedTodo}
    type="checkbox"
    value={id}
>
</input>

componentWillReceiveProps:

componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.

componentWillMount:

componentWillMount() is invoked immediately before mounting occurs. It is called before render().

2 Comments

it doesn't work I don't know why, but the props is changing but just doesnt get checked
ohh sorry there was a typo in componentWillReceiveProps method parameter use nextProps check the updated answer, it will work :)

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.