Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
280 views
in Technique[技术] by (71.8m points)

javascript - how to add multiple objects in reactjs?

I want to add new Objects when user click on checkbox. For example , When user click on group , it will store data {permission:{group:["1","2"]}}. If I click on topgroup , it will store new objects with previous one

{permission:{group:["1","2"]},{topGroup:["1","2"]}}. 

1st : The problem is that I can not merge new object with previous one . I saw only one objects each time when I click on the group or topgroup.

  onChange = value => checked => {
    this.setState({ checked }, () => {
      this.setState(prevState => {
        Object.assign(prevState.permission, { [value]: this.state.checked });
      });
    });
  };

  <CheckboxGroup
            options={options}
            value={checked}
            onChange={this.onChange(this.props.label)}
   />

Here is my codesanbox:https://codesandbox.io/s/stackoverflow-a-60764570-3982562-v1-0qh67

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It is a lot of code because I've added set and get to set and get state. Now you can store the path to the state in permissionsKey and topGroupKey. You can put get and set in a separate lib.js.

In this example Row is pretty much stateless and App holds it's state, this way App can do something with the values once the user is finished checking/unchecking what it needs.

const Checkbox = antd.Checkbox;
const CheckboxGroup = Checkbox.Group;

class Row extends React.Component {
  isAllChecked = () => {
    const { options, checked } = this.props;
    return checked.length === options.length;
  };

  isIndeterminate = () => {
    const { options, checked } = this.props;
    return (
      checked.length > 0 && checked.length < options.length
    );
  };

  render() {
    const {
      options,
      checked,
      onChange,
      onToggleAll,
      stateKey,
      label,
    } = this.props; //all data and behaviour is passed by App
    return (
      <div>
        <div className="site-checkbox-all-wrapper">
          <Checkbox
            indeterminate={this.isIndeterminate()}
            onChange={e =>
              onToggleAll(e.target.checked, stateKey)
            }
            checked={this.isAllChecked()}
          >
            Check all {label}
          </Checkbox>
          <CheckboxGroup
            options={options}
            value={checked}
            onChange={val => {
              onChange(stateKey, val);
            }}
          />
        </div>
      </div>
    );
  }
}

//helper from https://gist.github.com/amsterdamharu/659bb39912096e74ba1c8c676948d5d9
const REMOVE = () => REMOVE;
const get = (object, path, defaultValue) => {
  const recur = (current, path) => {
    if (current === undefined) {
      return defaultValue;
    }
    if (path.length === 0) {
      return current;
    }
    return recur(current[path[0]], path.slice(1));
  };
  return recur(object, path);
};
const set = (object, path, callback) => {
  const setKey = (current, key, value) => {
    if (Array.isArray(current)) {
      return value === REMOVE
        ? current.filter((_, i) => key !== i)
        : current.map((c, i) => (i === key ? value : c));
    }
    return value === REMOVE
      ? Object.entries(current).reduce((result, [k, v]) => {
          if (k !== key) {
            result[k] = v;
          }
          return result;
        }, {})
      : { ...current, [key]: value };
  };
  const recur = (current, path) => {
    if (path.length === 1) {
      return setKey(
        current,
        path[0],
        callback(current[path[0]])
      );
    }
    return setKey(
      current,
      path[0],
      recur(current[path[0]], path.slice(1))
    );
  };
  return recur(object, path, callback);
};

class App extends React.Component {
  state = {
    permission: { group: [] },
    topGroup: [],
    some: { other: [{ nested: { state: [] } }] },
  };
  permissionsKey = ['permission', 'group']; //where to find permissions in state
  topGroupKey = ['topGroup']; //where to find top group in state
  someKey = ['some', 'other', 0, 'nested', 'state']; //where other group is in state
  onChange = (key, value) => {
    //use set helper to set state
    this.setState(set(this.state, key, arr => value));
  };
  isIndeterminate = () =>
    !this.isEverythingChecked() &&
    [
      this.permissionsKey,
      this.topGroupKey,
      this.someKey,
    ].reduce(
      (result, key) =>
        result || get(this.state, key).length,
      false
    );

  toggleEveryting = e => {
    const checked = e.target.checked;
    this.setState(
      [
        this.permissionsKey,
        this.topGroupKey,
        this.someKey,
      ].reduce(
        (result, key) =>
          set(result, key, () =>
            checked
              ? this.plainOptions.map(({ value }) => value)
              : []
          ),
        this.state
      )
    );
  };
  onToggleAll = (checked, key) => {
    this.setState(
      //use set helper to set state
      set(this.state, key, () =>
        checked
          ? this.plainOptions.map(({ value }) => value)
          : []
      )
    );
  };
  isEverythingChecked = () =>
    [
      this.permissionsKey,
      this.topGroupKey,
      this.someKey,
    ].reduce(
      (result, key) =>
        result &&
        get(this.state, key).length ===
          this.plainOptions.length,
      true
    );
  plainOptions = [
    { value: 1, name: 'Apple' },
    { value: 2, name: 'Pear' },
    { value: 3, name: 'Orange' },
  ];
  render() {
    return (
      <React.Fragment>
        <h1>App state</h1>
        {JSON.stringify(this.state)}
        <div>
          <Checkbox
            indeterminate={this.isIndeterminate()}
            onChange={this.toggleEveryting}
            checked={this.isEverythingChecked()}
          >
            Toggle everything
          </Checkbox>
        </div>
        {[
          { label: 'group', stateKey: this.permissionsKey },
          { label: 'top', stateKey: this.topGroupKey },
          { label: 'other', stateKey: this.someKey },
        ].map(({ label, stateKey }) => (
          <Row
            key={label}
            options={this.plainOptions}
            // use getter to get state selected value
            // for this particular group
            checked={get(this.state, stateKey)}
            label={label}
            onChange={this.onChange} //change behaviour from App
            onToggleAll={this.onToggleAll} //toggle all from App
            //state key to indicate what state needs to change
            //  used in setState in App and passed to set helper
            stateKey={stateKey}
          />
        ))}
      </React.Fragment>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<link href="https://cdnjs.cloudflare.com/ajax/libs/antd/4.0.3/antd.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/antd/4.0.3/antd.js"></script>
<div id="root"></div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...