[英]Update state in React: array element nested in Object
我正在尝试构建onChange搜索功能。 在建议列表中,我的状态如下:
results: {
page: 1,
results: [
{value: 'popularity.desc', label: 'Popularity Descending'},
{value: 'popularity.asc', label: 'Popularity Ascending'},
{value: 'new value', label: 'new label'},
{value: 'vote_average.desc', label: 'Rating Descending'}
]
}
当用户选择{value: 'new value', label: 'new label'}
对象时。
如何将对象移到状态results
数组的第一个索引?
例如:选择对象之后。 状态应该是这样的:
results: {
page: 1,
results: [
{value: 'new value', label: 'new label'},
{value: 'popularity.desc', label: 'Popularity Descending'},
{value: 'popularity.asc', label: 'Popularity Ascending'},
{value: 'vote_average.desc', label: 'Rating Descending'}
]
}
我的想法是使用传播算子和过滤器,但我不知道如何实现。
选择项目方法:
onSuggestionSelected = (event, {suggestion, suggestionValue }) => {
console.log('Selected', suggestion); // {value: 'new value', label: 'new label'}
if (suggestion.media_type === 'movie') {
this.navigate('/search/movie', suggestionValue, suggestion);
} else if (suggestion.media_type === 'tv') {
this.navigate('/search/tv', suggestionValue, suggestion);
} else {
this.navigate('/search', suggestionValue, suggestion);
}
};
选择后,它将导航:
navigate = (pathname, queryValue, resultValue) => {
// ResultValue is that Object that I want to shift first.
this.props.history.push({
pathname,
search: `?query=${queryValue}`,
state: {results: this.state.data}});
};
//filtered the remaining item
let remainValue = result.filter((obj, key) => obj.value != suggestion.value);
//merge here
let newResult = [suggestion, ...remainValue]; //it will contain reordered item
您可以找到要放在数组中的result
的索引,然后将其放在数组的result
之前和之后。
例
class App extends React.Component {
state = {
results: {
page: 1,
results: [
{ value: "popularity.desc", label: "Popularity Descending" },
{ value: "popularity.asc", label: "Popularity Ascending" },
{ value: "new value", label: "new label" },
{ value: "vote_average.desc", label: "Rating Descending" }
]
}
};
putResultFirst = result => {
this.setState(previousState => {
const { results } = previousState.results;
const resultIndex = results.indexOf(result);
return {
results: {
...results,
results: [
result,
...results.slice(0, resultIndex),
...results.slice(resultIndex + 1)
]
}
};
});
};
render() {
return (
<div>
{this.state.results.results.map(result => (
<div key={result.id} onClick={() => this.putResultFirst(result)}>
{result.value} {result.label}
</div>
))}
</div>
);
}
}
首先,我们需要使用findIndex
查找index
,然后filter
当前状态以排除包含所选数据的对象。
我们需要做的最后一件事是使用扩展运算符...
将结果组合到一个数组中。
例:
const currentState = [ {value: 'popularity.desc', label: 'Popularity Descending'}, {value: 'popularity.asc', label: 'Popularity Ascending'}, {value: 'new value', label: 'new label'}, {value: 'vote_average.desc', label: 'Rating Descending'} ]; const selectedValue = {value: 'new value', label: 'new label'}; const onSelectionChange = (selected) => { const selectedIndex = currentState.findIndex(({ value }) => value === selected.value); const selectedItem = currentState[selectedIndex]; const stateExcludedItem = currentState.filter(({ value }) => value !== selected.value); const newState = [ selectedItem, ...stateExcludedItem ] // this.setState return newState; } const result = onSelectionChange(selectedValue); console.log(result);
要将选定的项目移到第一位置,可以使用Array.filter方法将未选定的项目作为数组获取,并构建一个新的结果数组:
selectedItem = this.state.results.results[clickedIndex]
unselectedItems = this.state.results.results.filter((item, index) => clickedIndex !== index)
因为“结果”状态是一个对象。 要更新处于该状态的对象,您应复制当前结果对象以创建一个新对象,以便更新状态。
results = {...this.state.results, results: [selectedItem, ...unselectedItems]}
您只想将所选项目移到结果数组的顶部,因此只需将所选项目的索引传输到事件处理程序,该处理程序将调用setState
方法。
示例代码:
class App extends React.Component { state = { results: { page: 1, results: [ {value: 'popularity.desc', label: 'Popularity Descending'}, {value: 'popularity.asc', label: 'Popularity Ascending'}, {value: 'new value', label: 'new label'}, {value: 'vote_average.desc', label: 'Rating Descending'} ] } }; handelClick = (clickedIndex) => { if(clickedIndex === 0) { return; } let selectedItem = this.state.results.results[clickedIndex], unselectedItems = this.state.results.results.filter((item, index) => clickedIndex !== index), results = {...this.state.results, results: [selectedItem, ...unselectedItems]}; this.setState({results}) }; render() { return <ul> {this.state.results.results.map((item, index) => <li key={item.label} onClick={this.handelClick.bind('', index)}>{item.label}</li>) } </ul> } } const renderFilterList = () => { ReactDOM.render(<App />, document.getElementById('react-app')); };
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="react-app"></div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.