我有一张船的桌子,并且正在尝试实现排序(使用表标题单击)和过滤(使用用户键入的文本字段)。
我对React如何处理组件状态感到困惑。
我的理解是componentDidUpdate()的工作方式如下:
基于这种理解,我希望componentDidUpdate()要
但是,当触发排序时,不会进行过滤。
我认为这会发生:
但这似乎发生了:
所以我对componentDidUpdate()的理解是参差不齐的,或者我对状态同步性的理解是。我已经读过状态可以在事件处理程序中异步。当我尝试检测是否应过滤时,也许分类后的船只还没有保存到状态中?
import React, { Component } from 'react';
import { SearchBar } from '../SearchBar';
import { Table } from '../Table/Table';
import { MoreButton } from '../MoreButton/MoreButton';
export class SearchableSortableTable extends Component {
constructor(props) {
super(props);
this.fetchShips = this.fetchShips.bind(this);
this.filterShips = this.filterShips.bind(this);
this.setSearchExpression = this.setSearchExpression.bind(this);
this.setSort = this.setSort.bind(this);
this.state = {
ships: [],
filteredShips: [],
searchExpression: '',
reverseSort: false
};
}
render() {
return (
this.state.error ?
<div>
<div>There was a problem fetching the ships, sorry.</div>
<div>{this.state.error}</div>
</div>
:
this.state.ships.length === 0 ? <h4>Loading...</h4> :
<div>
<div>
<SearchBar setSearchExpression={this.setSearchExpression} />
<MoreButton className="di" url={this.state.nextUrl} fetchShips={this.fetchShips} />
</div>
<div>
<Table ships={this.state.filteredShips} setSort={this.setSort} sortBy={this.state.columnName} reverse={this.state.reverseSort} />
</div>
</div>
);
}
componentDidMount() {
this.fetchShips(this.props.url);
}
componentDidUpdate(prevProps, prevState) {
if (this.state.columnName !== prevState.columnName || this.state.reverseSort !== prevState.reverseSort) {
this.sortShips();
}
// This conditional block is not entered when I sort.
if (this.state.ships !== prevState.ships || this.state.searchExpression !== prevState.searchExpression) {
this.filterShips();
}
}
async fetchShips(url) {
try {
const response = await fetch(url);
if (response['status'] && response['status'] === 200) {
const json = await response.json();
const ships = json['results'].map(this.mapShip);
this.setState({
ships: this.state.ships.concat(ships),
nextUrl: json['next']
});
} else {
this.setState({ error: `${response['status']} ${response['statusText']}` });
}
} catch (error) {
if (error instanceof TypeError && error.message.includes('NetworkError')) {
this.setState({ error: `${error.name} ${error.message}` });
} else {
throw error;
}
}
}
filterShips() {
const filteredShips = this.state.ships.filter(ship => {
return Object.values(ship).some(shipProp => shipProp.includes(this.state['searchExpression']))
});
this.setState({
filteredShips: filteredShips
});
}
setSearchExpression(event) {
this.setState({ searchExpression: event.target.value });
}
setSort(event) {
if (event && event['currentTarget'] && event['currentTarget']['attributes'] &&
event['currentTarget']['attributes']['name'] && event['currentTarget']['attributes']['name']['nodeValue']) {
const columnName = event['currentTarget']['attributes']['name']['nodeValue'];
this.setState({
columnName,
reverseSort: columnName === this.state.columnName ? !this.state.reverseSort : false
});
}
}
sortShips() {
if (this.state.columnName) {
const sortedShips = this.state.ships.sort((a, b) => {
const propA = a[this.state.columnName];
const propB = b[this.state.columnName];
if (!isNaN(+propA)) {
return this.state.reverseSort ? Number(propB) - Number(propA) : Number(propA) - Number(propB);
}
return this.state.reverseSort ? propB.localeCompare(propA) : propA.localeCompare(propB);
});
this.setState({ ships: sortedShips });
}
}
/**
* Maps a ship to its name, manufacturer, cost and starship class.
* @param ship The ship to be mapped.
*/
mapShip(ship) {
const { name, manufacturer, cost_in_credits, starship_class } = ship;
return Object.assign(
{
name,
manufacturer,
cost_in_credits,
starship_class
},
{}
);
}
}
答案 0 :(得分:0)
shouldComponentUpdate()方法适用于道具和状态。在您的示例中,在sort / filter事件之后,React将触发以下方法。尝试使用,
shouldComponentUpdate(nextProps, nextState) {
return this.state.value != nextState.value;
}