繁体   English   中英

在React中更新状态:嵌套在Object中的数组元素

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM