【问题标题】:react.js typescript spread(...) adding only the last elementreact.js typescript spread(...) 仅添加最后一个元素
【发布时间】:2020-07-02 21:51:46
【问题描述】:

我正在尝试在 react.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

我该如何解决这个问题?

【问题讨论】:

  • 你把 this.state.searched_chat_list 初始化成什么?
  • 使用includesconst list = data.filter(item => item.includes(letter));
  • 您应该更清楚地表述问题。你的问题是:“如何过滤所有以'a'开头的项目?”如果是 - 答案是data.filter(a => /a/g.test(a))
  • 你为什么使用地图?你在映射什么?

标签: javascript reactjs typescript react-typescript


【解决方案1】:

你当然想要这样的东西:

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而不是map(如果你试图做一个for-each,那么使用forEach而不是mapmap是用于将一个数组映射到另一个数组,这不是您在这里所做的。

  • 我将一个函数传递给setState,这样我就没有使用过时的状态值。您的setState 仅设置最后一个值的原因是您在循环的每次迭代中不断覆盖以前的值。

例如,假设你做了这样的事情:

// 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],即使在循环的最后一次迭代中 - 因为组件尚未重新渲染,所以状态还没有更新了。

基本上你正在这样做:

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

现在你能明白为什么只有最后一项被添加到数组中了吗?

如果你的新状态值依赖于之前的状态值,你应该总是传递一个函数给 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],这是我们想要的,尽管在您的情况下,您不需要迭代数组无论如何。

【讨论】:

    【解决方案2】:

    化繁为简,先过滤再添加:

    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)
    );
    

    【讨论】:

      猜你喜欢
      • 2021-09-02
      • 1970-01-01
      • 2020-10-15
      • 2012-09-29
      • 1970-01-01
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多