首页 > 解决方案 > 列表孩子没有正确更新?(反应/预演)

问题描述

我有以下组件

import {h, Component} from 'preact'
import {getPersons} from '../../lib/datalayer'
import Person from '../person'
import {SearchInput} from '../search'

export default class Persons extends Component {
  state = {
    allPersons: [],
    persons: [],
    search: ''
  }

  async fetchData () {
    try {
      const allPersons = await getPersons()
      this.setState({allPersons: allPersons.slice(), persons: allPersons.slice()})
    } catch (error) {
      ....
    }
  }

  constructor (props) {
    super(props)
    this.state = {
      allPersons: [],
      persons: [],
      search: ''
    }
    this.fetchData()
  }

  onSearchInput = (search) => {
    if (search === '') {
      this.setState({search: search, persons: this.state.allPersons.slice()})
    } else {
      const persons = this.state.allPersons.filter(p => p.name.toLowerCase().includes(search.toLowerCase())).slice()
      this.setState({search: search, persons: persons)})
    }
  }

  render () {
    const {persons} = this.state
    return (
      <div>
        <SearchInput onInputChange={this.onSearchInput} placeHolder={'filter: name'} />
        {persons.map(p => <Person person={p} />)}
      </div>
    )
  }
}

该页面呈现人员列表,顶部有一个过滤器。过滤器似乎工作正常,我通过控制台进行了测试。结果很好

问题是,如果我的列表包含对象:

[{name: 'thomas'}, {name: 'john'}, {name: 'marcus'}, {name: 'usa'}]

我在搜索输入中写道:“我们”

过滤器工作正常,结果是:

[{name: 'marcus'}, {name: 'usa'}] \\ (the expected result)

在页面中呈现此对象

[{name: 'thomas'}, {name: 'john'}] \\ (wrong, this are the two first elements of the list)

如果我搜索:'joh'

过滤器的结果是

[{name: 'john'}] \\ (this is fine)

并且页面只呈现

[{name: 'thomas'}] \\ (the first element in the list)

看起来渲染的元素数量很好,但是列表的子元素的内容没有重新渲染。

我的代码有什么问题?

标签: javascriptreactjspreact

解决方案


React 使用keys列表的子项来确定哪些项目发生了变化,哪些项目保持不变。由于您没有指定keyon person,因此它index是关键。

当索引是关键时,您可以看到如何将列表缩短为两个项目,从而显示列表中的前两个项目(现在缺少其他索引)。为了解决这个问题,你必须给这个人一个唯一的标识符作为键。

从您的对象中,假设name是唯一的(通常不是):

 {persons.map(p => <Person person={p} key={p.name} />)}

为什么需要密钥 - Docs


推荐阅读