Реагировать на выпадающий список / выбрать состояние без обновления - PullRequest
0 голосов
/ 03 октября 2019

Состояние обновления работает, если состояние, которое я пытаюсь обновить, находится вне массива пользователей. Но так как у меня несколько пользователей, мне нужно, чтобы состояние было внутри объектов и все равно обновлялось

Я продолжаю получать ошибку TypeError: Cannot read property 'name' of undefined

Я думал об установке состояния внутри циклано мне сказали, что это плохая идея.

Так что [e.target.name]: e.target.value был единственным кодом, который я мог найти для выпадающих списков.

Я пытался передать id для каждого из пользователей, но не знал, как изменить состояние, используя это или какое условие поставить.

import React, { Component } from 'react'
export default class App extends Component {

  state = {
    users: [
      {
        id: uuid(),
        firstName: 'John',
        lastName: 'Doe',
        favColor: 'None'
      },
      {
        id: uuid(),
        firstName: 'Jane',
        lastName: 'Doe',
        favColor: 'None'
      }
    ]
  }

  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value
    })
  }

  render() {

    return (
      <div>
        {this.state.users.map((user) => {

          return <div key={user.id}>

            <h1>{user.firstName}</h1>
            <h1>{user.lastName}</h1>

            <form>
              <select 
                  name="favColor" 
                  value={user.favColor} 
                  onChange={() => this.handleChange(user.id)}
              >
                <option value="None" disabled>None</option>
                <option value="Blue">Blue</option>
                <option value="Red">Red</option>
                <option value="Green">Green</option>
              </select>
            </form>

            <h1>Fav Color: {user.favColor}</h1>
            <hr />
          </div>
        })}
      </div>
    )
  }

}

Я ожидаю, что раскрывающиеся списки изменят состояние отдельно для каждого из пользователей

Ответы [ 3 ]

2 голосов
/ 03 октября 2019

Ваш handleChange метод не принимает правильные аргументы. Если вы хотите обновить один пользовательский элемент в массиве, вам нужно будет создать новую обновленную копию массива и сохранить обратно в состояние

handleChange = (e,id) => {
const updatedUser = {...this.state.users.find(x=>x.id ===id), favColor: e.target.value}
 this.setState({
    users:  [...this.state.users.filter(x==>x.id!==id),updatedUser]
    })
}

...
onChange={(e) => this.handleChange(e,user.id)}

. Чтобы упростить изменения состояния, я могу порекомендовать взглянуть на * 1005. * Immer

И, как правильно заметил @JosephD, это не будет поддерживать порядок, поэтому вам нужно будет сделать что-то вроде this.state.users.map(u => u.id === id ? { ...u, favColor: e.target.value } : u)

Вот кодовые окна на основе вашего кода:https://codesandbox.io/s/loving-cohen-do56l?fontsize=14

1 голос
/ 03 октября 2019

Вы обновляете состояние неверным образом;

Ваше состояние:

users: [
    { id: 1, ... },
    { id: 1, ... }
]

Ваше обновление / намерение:

users: [
    { id: 1, ... },
    { id: 1, ... }
]
favColor: color // intention, because you don’t pass event

Чтобы обновить правильный путь,вам необходимо:

  • передать событие и currentId для handleChange выбранного выпадающего списка. В противном случае вы не сможете узнать текущего пользователя. Кроме того, в вашем примере вы не пропустите событие, поэтому вы не можете получить информацию о раскрывающемся списке. Вызывая имя неопределенной ошибки.
  • проверьте, совпадает ли идентификатор пользователя с идентификатором выпадающего списка, и измените значение.

Этот пример должен работать для вас.

https://codesandbox.io/s/small-sea-mw08n

1 голос
/ 03 октября 2019
  <select 
     name="favColor" 
     value={this.state.favColor} 
     onChange={(e) => this.handleChange(e)}>  // first Change

 handleChange = (e) => {
    this.setState({
     favColor: e.target.value 
    })
  } // Second Change

Это будет работать для вас

...