реагирует. js машинописный текст (...) добавляет только последний элемент - PullRequest
2 голосов
/ 22 марта 2020

Я пытаюсь добавить элемент в массив в реагировать. js

this.state.chat_list.map(elem => {
  if (
    elem.name
      .toLowerCase()
      .indexOf(this.props.searching_username.toLowerCase()) !== -1
  ) {
    this.setState(
      { searched_chat_list: [...this.state.searched_chat_list, elem.name] },
      () => {
        console.log(this.state.searched_chat_list);
      }
    );
  }
});

Вот код.

Проблема Он добавляет только последний элемент из результата

Предположим, у меня есть a,ab,c,d,aad, и если я буду искать с a, он вернет только aad вместо a,ab,aad.

Как я могу решить это?

Ответы [ 2 ]

2 голосов
/ 22 марта 2020

Конечно, вы хотите что-то вроде этого:

this.setState(prev => ({
    searched_chat_list: [
        ...prev.searched_chat_list,
        prev.chat_list.filter(el =>
            el.name
                .toLowerCase()
                .includes(this.props.searching_username.toLowerCase())
        ),
    ],
}))

Я исправил несколько вещей:

  • Если вы фильтруете, вы должны использовать filter not map (и если вы пытаетесь сделать for-each, используйте forEach not map. map для отображения массива в другой массив, что здесь не то, что вы делаете .

  • Я передал функцию setState, чтобы не использовать устаревшие значения состояния. Причина, по которой setState устанавливал только последнее значение, заключается в том, что вы продолжали перезаписывать предыдущее значение на каждой итерации l oop.

Например, представьте, что вы сделали что-то вроде этого:

// State
const state = {
  myArray: [1, 2]
}

// Let's add this array to the one in state
[3, 4, 5, 6].forEach(num => {
  setState({
    // state.myArray is always [1, 2]
    myArray: [...state.myArray, num]
  })
})

Как вы думаете, результат здесь будет? Вы ожидаете [1, 2, 3, 4, 5, 6], но результат на самом деле [1, 2, 6].

Состояние обновляется только при повторном рендеринге, поэтому значение state.myArray ВСЕГДА [1, 2], даже в последний итерация l oop - потому что компонент еще не рендерился, поэтому состояние не обновилось.

В основном вы выполняя это:

  setState({myArray: [1, 2, 3]})
  setState({myArray: [1, 2, 4]})
  setState({myArray: [1, 2, 5]})
  setState({myArray: [1, 2, 6]})

Теперь вы можете видеть, почему только последний элемент добавляется в массив?

Если ваше новое значение состояния зависит от предыдущего значения состояния, вы всегда должны передавать function to setState:

// Let's pass a function to setState this time
[3, 4, 5, 6].forEach(num => {
  setState(prev => ({
    // prev is always the most up-to-date state value
    myArray: [...prev.myArray, num]
  }))
})

Значение prev всегда является наиболее актуальным значением состояния, поэтому результатом здесь будет [1, 2, 3, 4, 5, 6], что мы и хотели, хотя в вашем случае в любом случае вам не нужно было повторять массив.

0 голосов
/ 22 марта 2020

Упростите это, сначала отфильтруйте, затем добавьте:

const newList = this.state.chat_list.filter(
  elem =>
    elem.name
      .toLowerCase()
      .indexOf(this.props.searching_username.toLowerCase()) !== -1
);
this.setState(
  {
    searched_chat_list: [...this.state.searched_chat_list, ...newList]
  },
  () => console.log(this.state.searched_chat_list)
);
...