Vinicius Santana
Vinicius Santana

Reputation: 4106

How to let a parent component manage the state of child components in React?

I have 3 components built with React. They are:

How to manage the state of the clicked checkboxes. I would like Wrapper to know what checkboxes are checked.

class ListItem extends React.Component {
  render(){
    return (
      <li>
        <input type="checkbox" onChange={e => handleSelect(e.target.checked)} />
        <label>Checkbox 1</label>
      </li>
    )
  }
}

class List extends React.Component {
  getList(){
    const itemsList = this.props.list.map(
      (item, index) => (
        <ListItem key={index} item={item} />
      )
    )
   return itemsList;
  }
  
  render(){
    <ul>
      {this.itemsList}
    </ul>
  }
}

class Wrapper extends React.Component {
  const list = [
    {"id": 1, "label": "label 1"},
    {"id": 2, "label": "label 2"},
  ]

  render(){
    <List list={list} />
  }
}

Upvotes: 1

Views: 778

Answers (1)

0xRm
0xRm

Reputation: 1267

You should maintain the state of the list (and thus the checkboxes) in the Wrapper component instead, and pass that down to your List component.

Also, create the handler in the Wrapper component and pass that down too.

So your code becomes something like this:

class Wrapper extends React.Component {
    constructor() {
        this.state = [
            {"id": 1, "label": "label 1", checked: false},
            {"id": 2, "label": "label 2", checked: false}
        ]
    }

    handleChange(id, checked) {
        this.setState((state) => {
            return state.map(item => {
                return {
                   ...item,
                   checked: item.id === id ? checked : item.checked
                }
            });
       });
    }

    render() {
        <List list={this.state} onChange={this.handleChange} />
    }
}


class List extends React.Component {
  render(){
    <ul>
    { this.props.list.map((item, index) => (
          <ListItem key={index} item={item} handleChange={this.props.handleChange} />
    )}
    </ul>
  }
}

class ListItem extends React.Component {
  render(){
    const { item } = this.props;
    return (
      <li>
        <input type="checkbox" onChange={(e) => this.props.handleChange(item.id, e.target.checked)} />
        <label>{ item.label } </label>
      </li>
    )
  }
}

I didnt test this code, but I hope you get the gist of it. Maintain and change state in the top component, and use the lower components just to display and interact.

Upvotes: 1

Related Questions