reactjs - 我如何在某些 React 状态更新后获取数据(通过 GET)?
当用户点击其中一个按名称/电子邮件/日期排序的按钮时,用户应该从服务器获得一个新的渲染结果(发送一个新的 GET 请求)——分页也是同样的处理方式。
设置 this.setState({ [thestate]: [newStateVar] }) 本身并不能完成工作 ;)
那么复制这一行是“好做法”吗:
this.setState({
tickets: await api.getTickets(this.state.currentOrder, this.state.page),
});
从 componentDidMount() 中重写它?或者更好的是 - 创建一个只做这件事的方法 - 使用所有变量发送一个 get 请求 - 并在我需要重新渲染时调用它。(我甚至可以将这些行从 componentDidMount() 中移除,而不是重写这些行。这是正确的方法吗?)
我一直认为,每当 DOM 中的任何内容发生变化(例如 orderBy 按钮的 :active 类/样式变化)时——所有可以更新的东西都会被更新。我现在理解对了吗?错了吗?
编辑:哦,如果你看到其他值得提及以启发我的事情,也请告诉我。
import React from 'react';
import './App.scss';
import Pagi from './components/pagination/pagi';
export type AppState = {
tickets?: Ticket[],
currentOrder: string,
page: number,
}
const api = createApiClient();
export class App extends React.PureComponent<{}, AppState> {
state: AppState = {
currentOrder: 'date',
page: 1
}
async componentDidMount() {
this.setState({
tickets: await api....
});
}
componentDidUpdate(pP:any, pS:any, sS:any) {
if (this.state.page !== pS.page) {
this.setState({ page: this.state.page })
}
if (this.state.currentOrder !== pS.currentOrder) {
this.setState({ currentOrder: this.state.currentOrder })
}
}
renderTickets = (tickets) => {
const filteredTickets = tickets
.filter(...);
return (
<ul>
{showtkts}
</ul>
);
}
setOrder = (order:any) => {
console.log(this.state.currentOrder)
this.setState({
currentOrder: order.target.value,
});
}
setPage = (pageNum: number) => {
this.setState({
page: pageNum
})
}
render() {
const {tickets} = this.state;
return (<main>
<span> Order by: </span>
<button value='name' onClick={this.setOrder} className={ (this.state.currentOrder === 'name') ? 'selectedOrderItem' : '' }>
{/* <span role="img" aria-label="name">👤</span> */}
Name
</button>
<button value='email' onClick={this.setOrder} className={ (this.state.currentOrder === 'email') ? 'selectedOrderItem' : '' }>
{/* <span role="img" aria-label="email">📧</span> */}
Email
</button>
<button value='date' onClick={this.setOrder} className={ (this.state.currentOrder === 'date') ? 'selectedOrderItem' : '' }>
{/* <span role="img" aria-label="date">📅</span> */}
Date
</button>
</div>
<div className='resultsCount'>
{ tickets ? <div className='results'>Showing {tickets.length} results</div> : null }
{ (this.state.hidden === 0) ? '' : ((this.state.hidden === 1) ? <div className='results'>(1 ticket is hidden</div> : <div className='results'>({this.state.hidden} hidden tickets </div>) }
{ (this.state.hidden > 0) ? <div className='results showHiddenBtn' onClick={this.showHiddenTickets}>- restore) </div> : null }
</div>
<div>
{getTkts here}
</div>
<Pagi pages={tickets ? tickets.length : 1}/>
}
}
export default App;
答案#1
在某些 React 状态更新后,我如何获取数据(通过 GET)?
我认为你处理这个问题的方法不正确,流程应该是:
- 用户操作
- 获取数据
- (异步)状态更新
- 渲染
而不是相反的情况,即渲染触发数据获取。
我建议重新考虑你的组件设计,而不是试图让有缺陷的流程在你当前的实现中奏效。
请参阅此 codesandbox 示例: https://codesandbox.io/s/boring-matsumoto-ti9ot?file=/src/App.js
编辑:
来自下面的评论:
嗨,Nick,我还有另一个关于这个的问题。如果我按电子邮件订购结果(那会把页面重置为1,票据清空为[]),我该如何从点击筛选器到获取数据再到状态更新呢?如果我需要在获取数据之前先更新状态,该怎么办?
再次强调,不要担心手动计时渲染和更新,只需管理你的状态,让 React 处理更新和渲染,例如:
const [data, setData] = useState();
const [loading, setLoading] = useState(true);
const handleFetch = () => {
fetchData().then((res) => {
setData(res.data);
setLoading(false);
});
};
// Onload, fetch data and set loading to false when complete
useEffect(() => {
handleFetch();
}, []);
return (
<>
{loading ? <div>Loading...</div> : <div>data: {data}</div>}
<button onClick={handleFetch}>Click me to cause refetch data</button>
</>
);
对于您的使用场景,您要么只在加载完成后显示数据(实际上将数据重置为 []),要么在数据渲染之前显示某种占位符。不要先将状态设置为空,然后再获取数据,再重新设置状态。
