简体   繁体   中英

React: How to set dynamic states for an Array of checkboxes

I have a ServiceCard component which takes in an Object. This object may have a rights key with an Array of rights, each with disabled:true or disabled:false .

How would you setup the basic state for this kind of use case?

What the Rights Array looks like for a Service object:

在此处输入图片说明

(Just realized I miss-spelled turret :p)

Constructor and the Rights map function

constructor(props) {
  super(props);
  this.onChangeHandler = this.onChangeHandler.bind(this);
  this.updateService = this.updateService.bind(this);

  // How to define this.state for dynamic Rights Array?

  this.state = {
    serviceName: props.name,
    rights: props.rights
  }

  props.rights.map(right => {
    console.log(' map right', right)
    console.log(' this.state', this.state)
  })
}


// Later down in the render...
<ul>
  {
    rights.map(right =>
      <li key={ right.name }>
        <input type="checkbox"
               checked={ !right.disabled }
               onChange={ () => this.onChangeHandler(name, right) }/>
        <p>{ right.name }</p>
      </li>
    )
  }
</ul>

Full component code

import React, { Component } from 'react'

export default class ServiceCard extends React.Component {
  constructor(props) {
    super(props);
    this.onChangeHandler = this.onChangeHandler.bind(this);
    this.updateService = this.updateService.bind(this);
    this.deleteService = this.deleteService.bind(this);
  }

  onChangeHandler(name, right) {
    console.log('onChangeHandler...')
    console.log(' name', name)
    console.log(' right', right)

  }

  deleteService(serviceName) {
    this.props.deleteService(serviceName);
  }

  render () {
    const name = this.props.name;
    // console.log('this.props', this.props)
    const rights = this.props.rights;

    return (
      <li className="service-card-item">
        <section className="card">
          <div className="icon-connectdevelop service-icon"></div>
          <div className="service-details">
            <h3>{ name }</h3>
            <section className="rights-section">
              <ul>
                {
                  rights.map(right =>
                    <li key={ right.name }>
                      <input type="checkbox" checked={ !right.disabled } onChange={ () => this.onChangeHandler(name, right) }/>
                      <p>{ right.name }</p>
                    </li>
                  )
                }
              </ul>
              <div className="icon-cancel-circled" title="Delete Service" onClick={ () => this.deleteService(name) }></div>
            </section>
          </div>
        </section>
      </li>
    )
  }
}

As in the link Cloud Tseng provided, I initially setup my state with the rights array:

this.state = {
  serviceName: props.name,
  rights: props.rights
}

Then it was just a matter of getting the name of the Right that had it's checkbox changeHandled, using Ramda for some function mapping, returning a new Array of rights, then setting the state of rights to the new updated Array:

onChangeHandler with Ramda functional sexiness

onChangeHandler(name, right) {
  const serviceRights = this.state.rights;

  const findRight = R.curry((updatedRight, propsRight) => {
    if (updatedRight.name === propsRight.name) {
      propsRight.disabled = !propsRight.disabled;
    }
    return propsRight;
  });

  const updatedRights = R.map(findRight(right), serviceRights);
  console.log('  updatedRights', updatedRights)

  this.setState({
    rights: updatedRights
  }, console.log('  >>> State update completed:', this.state));
}

Before

在此处输入图片说明

After

在此处输入图片说明

Full fixed code

import React, { Component } from 'react'
import * as R from 'ramda'

export default class ServiceCard extends React.Component {
  constructor(props) {
    super(props);
    console.log('ServiceCard', props)
    this.onChangeHandler = this.onChangeHandler.bind(this);
    this.updateService = this.updateService.bind(this);
    this.deleteService = this.deleteService.bind(this);

    this.state = {
      serviceName: props.name,
      rights: props.rights
    }

    props.rights.map(right => {
      console.log(' map right', right)
      console.log(' this.state', this.state)
    });
  }

  onChangeHandler(name, right) {
    console.log('onChangeHandler...')

    const serviceRights = this.state.rights;

    const findRight = R.curry((updatedRight, propsRight) => {
      if (updatedRight.name === propsRight.name) {
        propsRight.disabled = !propsRight.disabled;
      }
      return propsRight;
    });

    const updatedRights = R.map(findRight(right), serviceRights);
    console.log('  updatedRights', updatedRights)

    this.setState({
      rights: updatedRights
    }, console.log('  >>> State update completed:', this.state));
  }

  updateService() {

  }

  deleteService(serviceName) {
    this.props.deleteService(serviceName);
  }

  render () {
    const name = this.props.name;
    // console.log('this.props', this.props)
    const rights = this.state.rights;

    return (
      <li className="service-card-item">
        <section className="card">
          <div className="icon-connectdevelop service-icon"></div>
          <div className="service-details">
            <h3>{ name }</h3>
            <section className="rights-section">
              <ul>
                {
                  rights.map(right =>
                    <li key={ right.name }>
                      {/* <input type="checkbox" checked={ !right.disabled } onChange={ () => this.onChangeHandler(name, right) }/> */}
                      <input type="checkbox" checked={ !right.disabled } onChange={ () => this.onChangeHandler(name, right) }/>
                      <p>{ right.name }</p>
                    </li>
                  )
                }
              </ul>
              <div className="icon-cancel-circled" title="Delete Service" onClick={ () => this.deleteService(name) }></div>
            </section>
          </div>
        </section>
      </li>
    )
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM