React JS 访问嵌套在状态中的数组

React JS accessing an array nested in state

class CreateEventForm extends Component {
  constructor(props) {
    super(props)
    this.state = {
      fields: {
        name: '',
        location: '',
        description: '',
        datetime: '',
      },
      friendsInEvent: [],
    },
    this.handleChange = this.handleChange.bind(this);
  }

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

  render() {

    const { friends, createEvent, addFriendsToEvent } = this.props
    const { fields: { name, location, description, datetime } } = this.state

    const setter = propName => event => {
      const nextFields = { ...this.state.fields }
      nextFields[propName] = event.target.value
      this.setState({ fields: nextFields })
    }

    return (
      <div {...cssForm}>
        <div>
          <Label label="Event Name" />
          <Field onChange={setter('name')} />

          <Label label="Event Date/Time" />
          <Field onChange={setter('datetime')} type="datetime-local" />

          <Label label="Event Location" />
          <Field onChange={setter('location')} />

          <Label label="Event Description" />
          <Field onChange={setter('description')} />

            <SubHeader title="Add Friends to the Event..." />
              <div>
                {friends
                  .mapEntries(([friendId, frn]) => [
                    friendId,
                    <div key={friendId}>
                      <input
                          value={friendId}
                          type='checkbox'
                          onChange={this.handleChange}
                          defaultChecked={false} />
                      {frn.firstName} {frn.lastName}
                    </div>,
                  ])
                  .toList()}
              </div>

            <Link to="/">
                <Button style="blue" name="Done" onClick={() => createEvent(this.state.fields)} />
            </Link>
        </div>
      </div>
    )
  }
}

export default CreateEventForm

上面的代码可以正常工作并按预期存储所有正确的值。但是我想将 friendsInEvent[ ] 移到 fields{ } 中。看起来像:

super(props)
 this.state = {
  fields: {
    name: '',
    location: '',
    description: '',
    datetime: '',
    friendsInEvent: [],
  },   
},
  this.handleChange = this.handleChange.bind(this);
}

我怎样才能做到这一点?我尝试过的所有操作都会破坏 handleChange(e) 函数或用 friendsInEvent 数组覆盖字段{}。

我想我必须在将数组移动到 this.state.field 之后更改 handleChange(e) 函数中的值?

此外,有没有办法合并我的两个函数 setter 和 handleChange(e)?我将它们分开,因为它们处理两种不同的类型(字符串和数组)。

谢谢。

从外观上看,您需要对 handleChange 进行以下更改:

handleChange(e) {
  const { checked, value } = e.target;

  // Ensure that you're destructuring from fields
  let { friendsInEvent } = { ...this.state.fields };
  if (checked) {
    friendsInEvent = [...friendsInEvent, value];
  } else {
    friendsInEvent = friendsInEvent.filter(el => el !== value)
  }

  // You need to take a copy of state, and then supply a new copy
  // of the the fields property which takes a copy of the old fields
  // property, and overwrites the friendsInEvent with the new data
  this.setState({
    ...this.state,
    fields: {...this.state.fields, friendsInEvent }
  }, () => console.log(this.state));
}

Here's a small React-free example of how this would work.

为什么你不能用下面的方法来做。

handleChange(e) {
    const { checked, value } = e.target
    let { friendsInEvent } = { ...this.state }
    if (checked) {
      friendsInEvent = [...friendsInEvent, value]
    } else {
      friendsInEvent = friendsInEvent.filter(el => el !== value)
    }
    let object = {};
    object.name = this.state.name;
    object.location = this.state.location;
    object.description = this.state.description;
    object.datetime = this.state.datetime;
    object.friendsInEvent = friendsInEvent;
    this.setState({
        fields: object
    })
  }

切勿在渲染中执行 setState。您不应该在渲染中执行 setState。事件处理程序应该在 render 方法之前处理,而不是在 render 内部处理。尝试避免在 render 中执行 setState。

const setter = propName => event => {
      const nextFields = { ...this.state.fields }
      nextFields[propName] = event.target.value
      this.setState({ fields: nextFields })
    }