网站搜索

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)?

我认为你处理这个问题的方法不正确,流程应该是:

  1. 用户操作
  2. 获取数据
  3. (异步)状态更新
  4. 渲染

而不是相反的情况,即渲染触发数据获取。

我建议重新考虑你的组件设计,而不是试图让有缺陷的流程在你当前的实现中奏效。

请参阅此 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>
  </>
);

对于您的使用场景,您要么只在加载完成后显示数据(实际上将数据重置为 []),要么在数据渲染之前显示某种占位符。不要先将状态设置为空,然后再获取数据,再重新设置状态。