Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reactjs checkboxlist component - Updating state changes in parent

I have a bunch of checkbox-list requirements. I will explain in detail. I have a bunch of languages say:

var languages = ["English", "German", "French", "Spanish", "Mandarin", "Tamil"]

I have a parent component which has a form where I have four sections, Say:

class Page extends React.Component {
  render() {
    return (
      <form>
        <h1>CanSpeak</h1> <chkboxlist someProp="speak" />
        <h1>CanSpeak</h1> <chkboxlist someProp="read" />
        <h1>CanSpeak</h1> <chkboxlist someProp="write" />
        <h1>CanSpeak</h1> <chkboxlist someProp="understand" />
        <button
          onClick={e => {
            console.log("Need the various chkboxlist values here");
            e.preventDefault();
          }}
        >
          Save
        </button>
      </form>
    );
  }
}

I want the chkboxlist component to keep track of the list of selected languages in each section and make them available in the "Save" button click handler. I wish to keep track of the state changes (list of selected languages under each section) in the "Page" component.

I do not want to use redux or some such external state management.

Now what is the way to create this chkboxlist component such that the state changes can be tracked in the parent Page component ? Are there any existing components which will fit this requirement and is used widely in the react ecosystem without having to reinvent the wheel ?

like image 924
Sankar Avatar asked Jun 30 '17 00:06

Sankar


People also ask

Does React update all children components once the state of a parent has changed?

As a result, the child components only update when the parent component's state changes with one of those functions. Directly mutating the props object is not allowed since this won't trigger any changes, and React doesn't notice the changes.

Can a child update the state of a parent React?

We can set Parent State from Children Component in ReactJs using the following approach. We will actually set the state of a parent in the parent component itself, but the children will be responsible for setting. We will create a function in parent to set the state with the given input.

Does component Rerender when parent state changes?

No, it will not re-render. If you pass any props to the component from the parent component and you update that prop in children or that prop update in the parent component so both will re-render.

How you will update the parent state by a child component?

To update the parent state from the children component, either we can use additional dependencies like Redux or we can use this simple method of passing the state of the parent to the children and handling it accordingly.


1 Answers

I don't know if pulling in a seperate component would be really useful - as it's only a really tiny piece of functionality.

Working fiddle here: https://jsbin.com/tusakexire/edit?html,js,output

You could do something like:

class Chkboxlist extends React.Component {
  constructor(props) {
      super(props) 
      this.state = {}
      props.values.map((v, i) => {
          this.state[v] = false
      })
  }

  onChange(key, value) {
      this.setState({ [key]: value }, (state) => {
          this.props.onChange(this.state)
      })
  }

  render() {
      return (
          <div className="list-group-item form-group">
                {this.props.values.map((value, i) => (
                    <div className="checkbox" key={i}>
                        <label>
                            <input 
                                onChange={(e) => this.onChange(value, e.target.checked)} 
                                type='checkbox' 
                                value={this.state[value]}
                            />
                            {value}
                        </label>
                    </div>
                ))}
          </div>
      )
  }
}

class Page extends React.Component {

  constructor(props) {
      super(props)
      this.state = {}
  }

  onChange(name, values) {
      this.setState({ [name]: values })
  }

  render() {
    const languages = ["English", "German", "French", "Spanish", "Mandarin", "Tamil"]


    return (
        <div className="container">
            <div className="row">
              <form className="form">

                <div className="list-group col-xs-6">
                    <h4>Can Speak</h4> 
                    <Chkboxlist 
                        onChange={(values) => this.onChange('speak', values)}
                        values={languages}
                    />
                </div>

                <div className="list-group col-xs-6">
                    <h4>Can Read</h4> 
                    <Chkboxlist 
                        onChange={(values) => this.onChange('read', values)}
                        values={languages}
                    />
                </div>

                <div className="list-group col-xs-6">
                    <h4>Can Write</h4> 
                    <Chkboxlist 
                        onChange={(values) => this.onChange('write', values)}
                        values={languages}
                    />
                </div>

                <div className="list-group col-xs-6">
                    <h4>Can Understand</h4> 
                    <Chkboxlist 
                        onChange={(values) => this.onChange('understand', values)}
                        values={languages}
                    />
                </div>

                <button
                  className="btn btn-primary"
                  onClick={(e) => {
                    console.log(this.state);
                    e.preventDefault();
                  }}
                >
                  Save
                </button>
              </form>
          </div>
      </div>
    );
  }
}

ReactDOM.render(<Page />, document.getElementById('app'))
like image 108
Chris Avatar answered Sep 25 '22 04:09

Chris