【问题标题】:React cannot update state twiceReact 不能两次更新状态
【发布时间】:2019-08-30 14:50:16
【问题描述】:

伙计们,我是 React 新手,我在一次调用中两次更新状态时遇到问题。
我正在尝试根据性别过滤 React Table 上可见的 行。

以下是我的状态,其中包含经过过滤和更新的 data 以及用于重置数据的备份 defaultData。

this.state = {


  data: [      

    {'id':1,first_name:'Ilka',last_name:'Riddel',email:'iriddel0@blogger.com',gender:'Female'},
    {'id':2,first_name:'Myrwyn',last_name:'Skinner',email:'mskinner1@cmu.edu',gender:'Male'},
    {'id':3,first_name:'Almira',last_name:'Kubu',email:'akubu2@google.ru',gender:'Female'},
    {'id':4,first_name:'Eloisa',last_name:'Maltster',email:'emaltster3@phoca.cz',gender:'Female'},
    {'id':5,first_name:'Vite',last_name:'Capin',email:'vcapin4@noaa.gov',gender:'Male'},
    {'id':6,first_name:'Zelig',last_name:'Crippin',email:'zcrippin5@blogtalkradio.com',gender:'Male'},
    {'id':7,first_name:'Persis',last_name:'Middlemiss',email:'pmiddlemiss6@discovery.com',gender:'Female'},
    {'id':8,first_name:'Amelina',last_name:'Biddy',email:'abiddy7@noaa.gov',gender:'Female'},
    {'id':9,first_name:'Darrell',last_name:'Kemme',email:'dkemme8@clickbank.net',gender:'Male'},
    {'id':10,first_name:'Kerianne',last_name:'Formby',email:'kformby9@berkeley.edu',gender:'Female'}
  ],
  defaultData: [      

    {'id':1,first_name:'Ilka',last_name:'Riddel',email:'iriddel0@blogger.com',gender:'Female'},
    {'id':2,first_name:'Myrwyn',last_name:'Skinner',email:'mskinner1@cmu.edu',gender:'Male'},
    {'id':3,first_name:'Almira',last_name:'Kubu',email:'akubu2@google.ru',gender:'Female'},
    {'id':4,first_name:'Eloisa',last_name:'Maltster',email:'emaltster3@phoca.cz',gender:'Female'},
    {'id':5,first_name:'Vite',last_name:'Capin',email:'vcapin4@noaa.gov',gender:'Male'},
    {'id':6,first_name:'Zelig',last_name:'Crippin',email:'zcrippin5@blogtalkradio.com',gender:'Male'},
    {'id':7,first_name:'Persis',last_name:'Middlemiss',email:'pmiddlemiss6@discovery.com',gender:'Female'},
    {'id':8,first_name:'Amelina',last_name:'Biddy',email:'abiddy7@noaa.gov',gender:'Female'},
    {'id':9,first_name:'Darrell',last_name:'Kemme',email:'dkemme8@clickbank.net',gender:'Male'},
    {'id':10,first_name:'Kerianne',last_name:'Formby',email:'kformby9@berkeley.edu',gender:'Female'}
  ]
};

我有处理方法来过滤数据和更新状态。

如果他们点击“显示所有男性”,则 handleShowOnlyMale 功能将过滤状态中的 data 并删除 data 中的所有女性,当他们点击 showAllFemale 然后表格将是empty,因为所有女性都已被删除。我不希望这种行为,并希望在表中的男性和女性记录之间产生类似切换的效果。

    handleResetData(){
    //console.log(this.state.data);
    this.setState({
        data: this.state.defaultData        
    })
  }

  handleShowOnlyMale(){
    //handleResetData();
    // this.setState((prevState) => {
    //     return {data: prevState.defaultData};
    //   }),
    this.setState({        
        data: this.state.data.filter(person => person.gender === 'Male')
    })    
  }

  handleShowOnlyFemale(){
    //handleResetData();
    // this.setState((prevState) => {
    //     return {data: prevState.defaultData};
    //   }),
    this.setState({        
        data: this.state.data.filter(person => person.gender === 'Female')
    })  
  }

我的解决方法是在开始过滤之前每次更新数据:this.state.defaultData。
我该如何正确地做到这一点?

下面是我的完整代码:

import React from "react";
import { render } from "react-dom";


// Import React Table
import ReactTable from "react-table";
import "react-table/react-table.css";

class App extends React.Component {
  constructor() {
    super();
    this.state = {


      data: [      

        {'id':1,first_name:'Ilka',last_name:'Riddel',email:'iriddel0@blogger.com',gender:'Female'},
        {'id':2,first_name:'Myrwyn',last_name:'Skinner',email:'mskinner1@cmu.edu',gender:'Male'},
        {'id':3,first_name:'Almira',last_name:'Kubu',email:'akubu2@google.ru',gender:'Female'},
        {'id':4,first_name:'Eloisa',last_name:'Maltster',email:'emaltster3@phoca.cz',gender:'Female'},
        {'id':5,first_name:'Vite',last_name:'Capin',email:'vcapin4@noaa.gov',gender:'Male'},
        {'id':6,first_name:'Zelig',last_name:'Crippin',email:'zcrippin5@blogtalkradio.com',gender:'Male'},
        {'id':7,first_name:'Persis',last_name:'Middlemiss',email:'pmiddlemiss6@discovery.com',gender:'Female'},
        {'id':8,first_name:'Amelina',last_name:'Biddy',email:'abiddy7@noaa.gov',gender:'Female'},
        {'id':9,first_name:'Darrell',last_name:'Kemme',email:'dkemme8@clickbank.net',gender:'Male'},
        {'id':10,first_name:'Kerianne',last_name:'Formby',email:'kformby9@berkeley.edu',gender:'Female'}
      ],
      defaultData: [      

        {'id':1,first_name:'Ilka',last_name:'Riddel',email:'iriddel0@blogger.com',gender:'Female'},
        {'id':2,first_name:'Myrwyn',last_name:'Skinner',email:'mskinner1@cmu.edu',gender:'Male'},
        {'id':3,first_name:'Almira',last_name:'Kubu',email:'akubu2@google.ru',gender:'Female'},
        {'id':4,first_name:'Eloisa',last_name:'Maltster',email:'emaltster3@phoca.cz',gender:'Female'},
        {'id':5,first_name:'Vite',last_name:'Capin',email:'vcapin4@noaa.gov',gender:'Male'},
        {'id':6,first_name:'Zelig',last_name:'Crippin',email:'zcrippin5@blogtalkradio.com',gender:'Male'},
        {'id':7,first_name:'Persis',last_name:'Middlemiss',email:'pmiddlemiss6@discovery.com',gender:'Female'},
        {'id':8,first_name:'Amelina',last_name:'Biddy',email:'abiddy7@noaa.gov',gender:'Female'},
        {'id':9,first_name:'Darrell',last_name:'Kemme',email:'dkemme8@clickbank.net',gender:'Male'},
        {'id':10,first_name:'Kerianne',last_name:'Formby',email:'kformby9@berkeley.edu',gender:'Female'}
      ],


      firstNameSelected: true,
      showMale: true,
      showFemale: true
    };

  }
  handleInputChange(value) {
      console.log(this.state.data);
    this.setState({ firstNameSelected: !this.state.firstNameSelected });
  }

  handleToUpperCaseFirstName(){    
    // this.setState({
    //         data: this.state.data.map(a => a.toUpperCase())
    //     }) 
  }

  handleResetData(){
    //console.log(this.state.data);
    this.setState({
        data: this.state.defaultData        
    })
  }

  handleShowOnlyMale(){
    //handleResetData();
    // this.setState((prevState) => {
    //     return {data: prevState.defaultData};
    //   }),
    this.setState({        
        data: this.state.data.filter(person => person.gender === 'Male')
    })    
  }

  handleShowOnlyFemale(){
    //handleResetData();
    // this.setState((prevState) => {
    //     return {data: prevState.defaultData};
    //   }),
    this.setState({        
        data: this.state.data.filter(person => person.gender === 'Female')
    })  
  }

  render() {
    const { data, firstNameSelected } = this.state;
    return (
      <div>
        <div>

          <button 
            onClick={this.handleToUpperCaseFirstName}>
            HIGHLIGHT FIRSTNAME (UPPERCASE)
          </button>

          <button 

            onClick={this.handleShowOnlyMale.bind(this)}>Show All Men</button>
          <button 

            onClick={this.handleShowOnlyFemale.bind(this)}>Show All The Ladies</button>
        </div>


        <ReactTable
          data={data}
          columns={[
            {

              columns: [
                {
                  Header: "First Name",
                  accessor: "first_name",
                  show: firstNameSelected
                },
                {
                  Header: "Last Name",
                  id: "last_name",
                  //show: firstNameSelected,
                  accessor: d => d.last_name
                }
              ]
            },
            {

              columns: [
                {
                  Header: "Email",
                  accessor: "email"
                },
                {
                  Header: "Gender",
                  accessor: "gender"
                }
              ]
            },

          ]}
          defaultPageSize={10}
          className="-striped -highlight"
        />
        <br />

      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

【问题讨论】:

  • 搜索任何 react TODO 项目/教程 - 过滤是基本功能,通常做得更好/更简单/更通用...

标签: reactjs react-table


【解决方案1】:

您可以保持数据处于状态并仅返回过滤后的值,如下所示:

 handleShowOnlyMale() {
   return this.state.data.filter(person => person.gender === 'Male');
 }

 handleShowOnlyFemale(){
   return this.state.data.filter(person => person.gender === 'Female');  
 }

【讨论】:

  • react 表并没有自动反映从 state.data 中过滤出来的数据,是不是因为 react 只是在 State 发生变化时才会渲染/重新渲染组件,而我们只是返回了 this。 state.data.filer State 不会自动更新 React Table
【解决方案2】:

为什么不用defaultData来过滤

handleShowOnlyMale(){
   this.setState({        
    data: this.state.defaultData.filter(person => person.gender === 'Male')
   })    
 }

handleShowOnlyFemale(){
   this.setState({        
    data: this.state.defaultData.filter(person => person.gender === 'Female')
  })  
 }

【讨论】:

  • defaultData 是什么?
  • defaultData 是原始数据的精确副本,因此我们可以将过滤后的数据回滚到其原始值
  • @ryan nghiem 可以,但这只是一种解决方法。我需要更新状态两次,因为我需要多次执行此模式(更新状态两次)
猜你喜欢
  • 2022-07-08
  • 2020-11-10
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-12
  • 2021-02-26
  • 1970-01-01
  • 2016-03-01
相关资源
最近更新 更多