React JS Storing an array of ids in state

寵の児 提交于 2019-12-12 10:21:52

问题


I have a prop called friends which is being listed as a checkboxes (default: unselected).

Example output:

o Bob Smith

o Tom Brown

How can I save the id's of all the names that are selected?

E.g. both are ticked/selected -> ids 1 and 2 is stored.

This is what I have so far:

class SelectFriends extends Component {
  constructor(props) {
  super(props)
  this.state = {
    SelectedFriendsIds: [],
  }
}

render() {
  const { SelectedFriendsIds } = this.state
  const { userId, friends, addFriendsTo } = this.props

return (
    <div>
      <SubHeader title="Add Friends..." />
      <div>
        {friends
          .mapEntries(([friendId, frn]) => [
            friendId,
            <div key={friendId}>
              <input
                  value={friendId}
                  type='checkbox'
               // onChange={ () => console.log("do something")
                  defaultChecked={false} />
              {frn.firstName} {frn.lastName}
            </div>,
          ])
          .toList()}
      </div>
        <div>
          <Button style="blue" name="Done" onClick={() => addFriendsTo(SelectedFriendIds, userId)} />
        </div>
    </div>
  )
 }
}

export default SelectFriends

回答1:


Here's a slightly simplified version of your code with a new function handleChange that is called every time a checkbox is checked/unchecked.

We take a copy of the state and extract selectedFriendsIds. If an id is to be added to the state setState is called with a new array of the new value merged into selectedFriendsIds. If checkbox is unchecked the setState is called with a filtered copy of selectedFriendsIds instead.

You might want to run this snippet full page as it logs the state to the console after each change to show you the output.

class SelectFriends extends React.Component {

  constructor(props) {
    super(props);
    this.state = { selectedFriendsIds: [] }
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const { checked, value } = e.target;
    let { selectedFriendsIds } = this.state;
    if (checked) {
      selectedFriendsIds = [...selectedFriendsIds, value];
    } else {
      selectedFriendsIds = selectedFriendsIds.filter(el => el !== value);
    }
    this.setState({ selectedFriendsIds }, () => console.log(this.state));
  }


  render() {
  
    const { friends } = this.props;
  
    return (
      <div>
        <h2>Add Friends</h2>
          {friends.map(({ friendId, frn }) => {
            return (
              <div key={friendId}>
                <input value={friendId} type="checkbox" onChange={this.handleChange} />{frn}
              </div>
            );
          })}
      </div>
    )
  }
}

const friends = [
  { friendId: 1, frn: 'Bob' },
  { friendId: 2, frn: 'Davros' },
  { friendId: 3, frn: 'Daisy' }
];

ReactDOM.render(
  <SelectFriends friends={friends} />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>

Also available in a jsfiddle.




回答2:


You need to check if the value is already in your selected list and add it if its not there else remove the value onChange event of the checkbox. Check the sample code below

class SelectFriends extends Component {
  constructor(props) {
  super(props)
  this.state = {
    SelectedFriendsIds: [],
  }
}

onChange = (val) => {
   const SelectedFriendsIds = [...this.state.SelectedFriendsIds];
   const presentIndex = SelectedFriendsIds.indexOf(val)
   if(presentIndex > 0) {
      SelectedFriendsIds.splice(presentIndex, 1);
   } else {
      SelectedFriendsIds.push(val);
   }
   this.setState({SelectedFriendsIds})

}
render() {
  const { SelectedFriendsIds } = this.state
  const { userId, friends, addFriendsTo } = this.props

return (
    <div>
      <SubHeader title="Add Friends..." />
      <div>
        {friends
          .mapEntries(([friendId, frn]) => [
            friendId,
            <div key={friendId}>
              <input
                  value={friendId}
                  type='checkbox'
                  onChange={ () => this.onChange(friendId)
                  defaultChecked={false} />
              {frn.firstName} {frn.lastName}
            </div>,
          ])
          .toList()}
      </div>
        <div>
          <Button style="blue" name="Done" onClick={() => addFriendsTo(SelectedFriendIds, userId)} />
        </div>
    </div>
  )
 }
}

export default SelectFriends



回答3:


You can simply use array.push for adding ids on check array.filter to retrieve single id and array.slice to remove single id.




回答4:


the code can be modified like this

  class SelectFriends extends Component {
    constructor(props) {
        super(props)
        this.state = {
            SelectedFriendsIds: {},  //CHANGING INTO OBJ FOR EASIER MANIPULATION
        }
    }

    render() {
        const { SelectedFriendsIds } = this.state
        const { userId, friends, addFriendsTo } = this.props

        return (
            <div>
                <SubHeader title="Add Friends..." />
                <div>
                    {friends
                        .mapEntries(([friendId, frn]) => [
                            friendId,
                            <div key={friendId}>
                                <input
                                    checked={friendId}   //USE CHECKED ALWAYS FOR CHECKBOXES
                                    type='checkbox'
                                    onChange={(e) => {
                                        let x = SelectedFriendsIds;
                                    if (e.target.checked) {
                                        x[friendId] = true;
                                    }
                                    else {
                                        delete x[friendId];
                                    }
                                    this.setState({
                                        SelectedFriendsIds: x
                                    })
                                    }} />
                                {frn.firstName} {frn.lastName}
                            </div>,
                        ])
                        .toList()}
                </div>
                <div>
                    <Button style="blue" name="Done" onClick={() => addFriendsTo(SelectedFriendIds, userId)} />
                </div>
            </div>
        )
    }
}

export default SelectFriends

If you need array of selected friends, just use

Object.keys(this.state.SelectedFriendsIds)



回答5:


I would like to suggest a small improvement to the design of your component, which also resolves the problem of how to maintain state of selected friend IDs efficiently. Frankly, there is no need to maintain state of selected Ids. Instead, please maintain a state of friends collection - where each object representing a friend, has 'selected' property. This way, You'd be able to easily filter selected ones and send this information to upper component. Below is the code snippet explaining this fully:

import React, { Component } from 'react';
import * as _ from 'lodash';
import PropTypes from 'prop-types';

class FriendsList extends Component {

state = {
    friends: []
}

constructor(props) {

    super(props);

    this.onAdd = this.onAdd.bind(this);

    this.state.friends = [ {id: 1, name: 'John', selected: false}, 
        { id: 2, name: 'Ally', selected: false},
        { id: 3, name: 'Becky', selected: false},
        { id: 4, name: 'Frank', selected: false},
        { id: 5, name: 'Mark', selected: true},
        { id: 6, name: 'Alice', selected: true}
    ];
}

onCheckboxChange(event, n) {
    n.selected = !n.selected;
    this.forceUpdate();
}

onAdd() {
    const selectedFriends = _.filter( this.state.friends, (friend) => {
        return friend.selected === true;
    });
    this.props.onAdd(selectedFriends);
}

render() {
    const { friends } = this.state;
    return (
        <div>
            {friends.map(n => {
                return (
                    <div key={n.id}>
                        {n.name} <input type="checkbox" onChange={(event) => this.onCheckboxChange(event, n)} checked={n.selected}/>
                    </div>
                );
            })}
            <button onClick={this.onAdd}>Add Friends</button>
        </div>
    );
}
}
FriendsList.propTypes = {
  onAdd: PropTypes.func,
};
export default FriendsList;


来源:https://stackoverflow.com/questions/48499813/react-js-storing-an-array-of-ids-in-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!