React表格排序后点击行恢复原位置问题求助
Hey there! Let's break down why your table is jumping back to its original order after sorting and clicking a row, and how to fix it for good.
What's Causing the Problem?
The core issue is how you're managing sorted data in your component state, combined with a flawed props update check:
- State vs Props Sync Issue: You're storing a sorted copy of
insurancein your component state, but when the component receives new props (even if onlyselectedInschanges, notinsurance), yourcomponentWillReceivePropsmethod incorrectly replaces the sorted state data with the original props data. This happens becausethis.state.insurance != nextProps.insurancechecks for reference equality, not content equality—since the sorted array is a new reference, this condition always evaluates to true when any prop updates. - Outdated Lifecycle Method:
componentWillReceivePropsis deprecated in React, and using it here creates unnecessary data sync problems.
The Best Fix: Dynamic Sorting in Render
Instead of storing sorted data in state, we can calculate the sorted list dynamically during each render. This eliminates the need to sync state and props, and keeps your code cleaner. Here's how to adjust your component:
Step 1: Simplify Component State
Remove the insurance field from state—we only need to track sorting metadata:
constructor(props) { super(props); this.state={ orderby: '', order: {}, } this.sort = this.sort.bind(this); }
Step 2: Update the Sort Method
Now the sort method only needs to update the sorting key and direction in state, not manipulate the data itself:
sort(event){ const { order } = this.state; const sortKey = event.target.id; // Toggle sort direction for the clicked column const newOrder = { ...order, [sortKey]: !order[sortKey] }; this.setState({ orderby: sortKey, order: newOrder }); }
Step 3: Dynamically Sort Data in Render
Calculate the sorted list directly in the render method using the original props data and current sorting state:
render() { const { selectedIns, onSelectInsurance, insurance: originalInsurance } = this.props; const { orderby, order } = this.state; // Sort data on each render based on current sorting rules let sortedInsurance = originalInsurance || []; if (orderby) { sortedInsurance = _.orderBy( sortedInsurance, (o) => typeof o[orderby] === 'string' ? o[orderby].trim().toLowerCase() : o[orderby], order[orderby] ? 'asc' : 'desc' ); } return ( <div > <table > <thead > <tr > <th id='Company' onClick={this.sort}> Insurance Company {order.Company ? <i className="fa fa-sort-asc"/> : <i className="fa fa-sort-desc"/>} </th> <th id='Verified' onClick={this.sort}> Verified {order.Verified ? <i className="fa fa-sort-asc"/> : <i className="fa fa-sort-desc"/>} </th> </tr> </thead> <tbody > {sortedInsurance.map(insuranceItem => ( <tr key={insuranceItem.InsID} onClick={() => onSelectInsurance(insuranceItem)} > <td title={insuranceItem.Company ? insuranceItem.Company : insuranceItem.TempInsurance}> {insuranceItem.Company ? insuranceItem.Company : insuranceItem.TempInsurance} </td> <td > {insuranceItem.Verified === 1 ? 'Yes' : 'No'} </td> </tr> ))} </tbody> </table> </div> ); }
Step 4: Remove the Deprecated Lifecycle Method
Delete the componentWillReceiveProps method entirely—we no longer need it since we're dynamically sorting in render.
Why This Works
By calculating the sorted list on each render:
- We always use the latest props data, so there's no risk of stale state overriding sorted data.
- We eliminate the need to sync state and props, which was the root cause of your table reverting to original order.
- The code becomes simpler and easier to maintain.
内容的提问来源于stack exchange,提问作者Jane Fred

