Javascript 列表子项未正确更新?(反应/预演)
我有以下组件Javascript 列表子项未正确更新?(反应/预演),javascript,reactjs,preact,Javascript,Reactjs,Preact,我有以下组件 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: [], perso
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: '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)
看起来渲染的元素数量不错,但列表中子元素的内容没有被重新渲染
我的代码有什么问题?React使用列表子项上的
键来确定哪些项已更改,哪些项保持不变。由于您没有在person上指定键
,因此需要索引
作为键
当索引为键时,您可以看到如何将列表缩短为两项,显示列表中的前两项(其他索引现在丢失)。要解决这个问题,您必须在此人身上指定一个唯一标识符作为密钥
从对象中,假设名称
是唯一的(通常不是):
{persons.map(p=>)}
React使用列表子项上的键来确定哪些项已更改,哪些项保持不变。由于您没有在person上指定键
,因此需要索引
作为键
当索引为键时,您可以看到如何将列表缩短为两项,显示列表中的前两项(其他索引现在丢失)。要解决这个问题,您必须在此人身上指定一个唯一标识符作为密钥
从对象中,假设名称
是唯一的(通常不是):
{persons.map(p=>)}
我无法使用react重现错误,确实删除了一些不需要的片段,并为每个元素添加了唯一id(如果您没有给每个元素一个唯一的键,react将投诉,并且可能会预作用)
const Person=React.memo(道具=>(
{JSON.stringify(props,未定义,2)}
));
类。组件{
状态={
所有人士:[
{name:'aaa',id:1},
{name:'aab',id:2},
{name:'abb',id:3},
{name:'bbb',id:4},
{姓名:'bbc',id:5},
],
人员:[
{name:'aaa',id:1},
{name:'aab',id:2},
{name:'abb',id:3},
{name:'bbb',id:4},
{姓名:'bbc',id:5},
],
搜索:“”,
};
onSearchInput=搜索=>{
如果(搜索==''){
//这里不需要切片
这是我的国家({
搜索:搜索,
人物:this.state.allPersons,
});
}否则{
//筛选器已复制所有人员
const persons=this.state.allPersons.filter(p=>
p、 name.toLowerCase().includes(search.toLowerCase())
);
this.setState({search:search,persons:persons});
}
};
render(){
const{persons}=这个州;
返回(
this.onSearchInput(e.target.value)}
占位符={'filter:name'}
/>
{persons.map(p=>(
))}
);
}
}
ReactDOM.render(
,
document.getElementById('root'))
);代码>
我无法使用react重现错误,确实删除了一些不需要的片段,并为每个元素添加了唯一id(如果您没有给每个元素一个唯一的键,react将投诉,并且可能会预作用)
const Person=React.memo(道具=>(
{JSON.stringify(props,未定义,2)}
));
类。组件{
状态={
所有人士:[
{name:'aaa',id:1},
{name:'aab',id:2},
{name:'abb',id:3},
{name:'bbb',id:4},
{姓名:'bbc',id:5},
],
人员:[
{name:'aaa',id:1},
{name:'aab',id:2},
{name:'abb',id:3},
{name:'bbb',id:4},
{姓名:'bbc',id:5},
],
搜索:“”,
};
onSearchInput=搜索=>{
如果(搜索==''){
//这里不需要切片
这是我的国家({
搜索:搜索,
人物:this.state.allPersons,
});
}否则{
//筛选器已复制所有人员
const persons=this.state.allPersons.filter(p=>
p、 name.toLowerCase().includes(search.toLowerCase())
);
this.setState({search:search,persons:persons});
}
};
render(){
const{persons}=这个州;
返回(
this.onSearchInput(e.target.value)}
占位符={'filter:name'}
/>
{persons.map(p=>(
))}
);
}
}
ReactDOM.render(
,
document.getElementById('root'))
);代码>
[{name: 'thomas'}] \\ (the first element in the list)
{persons.map(p => <Person person={p} key={p.name} />)}