React单次调用无法两次更新状态及表格性别过滤切换问题
解决React Table性别过滤时的数据切换问题
嘿,我完全懂你现在的困扰!你遇到的核心问题其实是直接修改了用于展示的state数据,导致原始数据被覆盖,后续过滤找不到需要的记录。你的临时重置方案能work,但其实有更优雅的实现方式,不用每次过滤前都重置数据,咱们一步步来改:
问题根源
你之前的做法是每次点击按钮就直接修改this.state.data,比如点击“Show All Men”后,data就变成了只有男性的数组;这时再点“Show All The Ladies”,是基于已经过滤过的男性数组去过滤女性,自然找不到数据,表格就空了。
正确思路:保留原始数据,用过滤条件动态计算展示数据
我们只需要把过滤条件存在state里,而不是直接修改展示数据。渲染表格时,始终从原始的defaultData出发,根据当前的过滤条件计算出要展示的内容。这样原始数据永远不会被修改,切换过滤条件时就能正确拿到对应的数据。
修改后的完整代码
import React from "react"; import { render } from "react-dom"; import ReactTable from "react-table"; import "react-table/react-table.css"; class App extends React.Component { constructor() { super(); this.state = { // 只保留一份原始数据,不用重复存储data 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, // 新增过滤条件:可选值 'all' | 'male' | 'female' activeFilter: 'all' }; } handleInputChange(value) { this.setState({ firstNameSelected: !this.state.firstNameSelected }); } handleToUpperCaseFirstName(){ // 如果你需要实现这个功能,也应该基于defaultData处理后生成新数组,不要修改原始数据 // 比如: // this.setState(prevState => ({ // defaultData: prevState.defaultData.map(person => ({ // ...person, // first_name: person.first_name.toUpperCase() // })) // })) } handleShowOnlyMale(){ // 只修改过滤条件,不修改数据 this.setState({ activeFilter: 'male' }) } handleShowOnlyFemale(){ this.setState({ activeFilter: 'female' }) } handleShowAll(){ // 新增显示全部的按钮逻辑 this.setState({ activeFilter: 'all' }) } render() { const { defaultData, firstNameSelected, activeFilter } = this.state; // 根据当前过滤条件计算要展示的数据 const filteredData = defaultData.filter(person => { if (activeFilter === 'male') { return person.gender === 'Male'; } else if (activeFilter === 'female') { return person.gender === 'Female'; } // 默认显示全部 return true; }); return ( <div> <div> <button onClick={this.handleToUpperCaseFirstName.bind(this)}> 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> <button onClick={this.handleShowAll.bind(this)}>Show All</button> </div> <ReactTable data={filteredData} // 用计算后的过滤数据 columns={[ { columns: [ { Header: "First Name", accessor: "first_name", show: firstNameSelected }, { Header: "Last Name", id: "last_name", 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"));
关键修改点说明
- 移除重复的
datastate:只保留一份原始的defaultData,避免数据冗余和意外覆盖。 - 新增
activeFilterstate:用这个变量来记录当前的过滤状态,而不是直接修改数据。 - 动态计算展示数据:在
render方法里根据activeFilter从defaultData过滤出要展示的内容,确保每次过滤都是基于原始数据。 - 简化按钮事件逻辑:按钮点击只需要修改
activeFilter的值,不用再处理数据重置和过滤的复杂逻辑。
这样修改后,你就能轻松实现男女记录的切换,再也不会出现表格为空的问题,逻辑也更清晰易维护~
内容的提问来源于stack exchange,提问作者TwoThumbSticks
相关产品推荐
相关产品推荐

