Обновить объект в массиве с помощью обработчика

#javascript #reactjs

#javascript #reactjs

Вопрос:

У меня есть функциональный Item компонент, который использует React.memo . Компонент отображает несколько разных полей ввода. Я пытаюсь обновить значение состояния для измененного, Item но я не уверен, как это сделать без изменения или изменения текущего состояния, поскольку моя первоначальная реализация вызвала nextProps и prevProps для React.memo того, чтобы быть одинаковым.

Вот мой обработчик в родительском компоненте контейнера:

 handleItemChange = (item, event, index) => {

    item[event.target.name] = event.target.value;
    this.setState({
      job: this.state.job
    })

}
 

Мое состояние выглядит примерно так:

 this.state = {
    job: {
        items: [{id: 1, quantity: 3, name: "test"}, {id: 2, quantity: 1, name: "test 2"}, {id: 3, quantity: 1, name: "test 3"}]
    }
} 
 

В моем компоненте формы я отображаю список Items , подобный этому:

 {this.props.job.items.map((i, index) => (
    <Item key={i.id} handleItemChange={this.props.handleItemChange} item={i} index={index} />
 ))}
 

Затем в моем Item компоненте (который запоминается) Я визуализирую поля ввода и вызываю обработчик:

 function areEqual(prevProps, nextProps) {

  console.log(prevProps.job_item.quantity)
  console.log(nextProps.job_item.quantity)

  return true
};

const Item = React.memo(props => {

  return (


    <Grid container spacing={3}>
      <Grid item xs={1}>
          <FormControl>
            <TextField
              name="quantity"
              value={props.item.quantity}
              label="quantity"
              variant="outlined"
              type="number"
              onChange={e => props.handleItemChange(props.item, e, props.index)}
              InputLabelProps={{
                shrink: true,
              }}
            />
          </FormControl>
        </Grid>
    </Grid>



  )

}, areEqual);

export default Item;
 

В этом текущем коде оба объекта prop areEqual содержат одинаковые значения, и я считаю, что это связано с тем, что я изменяю item непосредственно в handleItemChange обработчике, но я не уверен, как изменить значение элемента, не ссылаясь на него напрямую. Я посмотрел на создание глубокой копии объекта массива, но я не уверен, как это сделать. Я также передаю значение индекса, поэтому this.state.job.items[index] для моего случая возможна ссылка.

Комментарии:

1. пожалуйста, приходите с рабочим фрагментом, если у вас есть фрагмент, который четко показывает вашу проблему, он решит вашу проблему намного быстрее, чем без фрагмента

Ответ №1:

Может быть, это работает?

 handleItemChange = (item, event, index) => {
  // copy the state, since state should be immutable
  let clonedJob = [...this.state.job];

  // Find item in new state
  let clonedItem = clonedJob.find(i => return i.id === item.id);

  // Update that cloned item
  clonedItem[event.target.name] = event.target.value;

  // Update state
  this.setState({
    job: clonedJob
  })
}