javascript - 在 React 中引用前一个状态时在 setState 中使用回调
问题描述
我正在对表格进行排序,它应该按字母顺序对列进行排序,按字母顺序反转,并在每次调用该方法时返回原始形式。
这是我的代码:
export default class GenericTable extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
otherStudd: '',
currentSort: 'default',
rows: this.props.rows, // I receive the rows data on props
};
}
onSortChange = index => {
const sortMap = {
default: 'up',
up: 'down',
down: 'default',
};
const { currentSort, currentIndex } = this.state;
const nextSort = currentIndex === index ? sortMap[currentSort] : 'default';
const newRows = [...this.state.rows]; // line 40 - here is the error
switch (nextSort) {
case 'up':
newRows.sort((a, b) => (a.cells[index] <= b.cells[index] ? -1 : 1));
break;
case 'down':
newRows.sort((a, b) => (b.cells[index] <= a.cells[index] ? -1 : 1));
break;
}
this.setState({
rows: newRows,
currentSort: nextSort,
currentIndex: index,
});
};
...
}
我认为代码看起来正确,但我收到一条 es-lint 错误消息:
Line 40:25: Use callback in setState when referencing the previous state react/no-access-state-in-setstate
它应该做一个回调函数,但我不知道如何让它工作。
有任何想法吗?
解决方案
将 props 分配给 state 并从那里使用它们是一种 React 反模式(您可以在此处阅读有关它的更多信息)。
当您尝试实现的场景需要时,推荐的方法是创建一个完全受控的组件,或者在这种情况下,一个部分受控的组件,不仅rows
从道具使用,而且对它们的任何转换也通过道具(在这种情况下,排序)。
下面的代码片段演示了手头问题的简化版本。我们创建了一个Parent
存储rows
其状态的组件,并提供了一个执行排序的方法。然后它呈现一个完全受控的Child
组件,该组件不需要拥有自己的状态,而是接收行以及它的排序器功能作为道具。
该sortRows
方法说明了如何使用setState
回调,与提供状态对象相比,该回调提供了在状态上产生更一致的结果的好处。
class Child extends React.PureComponent {
render() {
const { rows, sortRows } = this.props;
return (
<div>
<ul>{ rows.map((row, i) => (<li key={ i }>{ row }</li>)) }</ul>
<button onClick={ () => { sortRows(true) }}>Sort Ascending</button>
<button onClick={ () => { sortRows(false) }}>Sort Descending</button>
</div>
);
}
}
class Parent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
rows: ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter']
};
}
sortRows = (isSortAscending) => {
this.setState((prevState) => ({
rows: prevState.rows.slice().sort((a, b) => {
if (a < b) return -(isSortAscending ? 1 : -1);
if (a > b) return (isSortAscending ? 1 : -1);
return 0;
})
}));
}
render() {
return <Child rows={ this.state.rows } sortRows={ this.sortRows } />;
}
}
ReactDOM.render(<Parent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
推荐阅读
- apache-spark - 使用 PySpark 和 Kafka 进行结构化流处理,Py4JJavaError: An error occurred while calling o70.awaitTermination
- consensus - 在 Raft 中,follower 何时知道条目已提交?Can an out-of-date node can win a election?
- spring - Activiti 边界事件未在 Spring Boot 集成测试中触发
- google-apps-script - G Script - 如何在 G Drive 中查找文件名的一部分
- php - 如何在 Laravel 4 中使用 put Method on Cache?
- javascript - 如何避免为 dataTables 中的每个按钮使用自定义脚本?
- rxjs - 可观察到的,它发出精确地按一定时间间隔分开的事件
- jwt - CAS JWT Service Ticket 文档中的“返回的断言长度”是什么意思?
- react-native - 显示 React Native 的 Flatlist 数组
- apollo - 使用 apollo-link-state 保存 @client 数据时出现“selectionSet 为空”错误