reactjs - Hur hämtar jag data (via GET) efter att någon React-tillstånd har uppdaterats?


När en användare klickar på en av knapparna för sortering (efter namn/e-post/datum) - ska användaren få ett nytt renderat resultat från servern (genom att skicka en ny GET-förfrågan) - och samma gäller för sidnumrering.

att sätta this.setState({ [thestate]: [newStateVar] }) gör inte jobbet på egen hand ;)

Så är det "en bra praxis" att kopiera denna rad:

    this.setState({
        tickets: await api.getTickets(this.state.currentOrder, this.state.page),
    });

från componentDidMount() och skriva om det? eller ännu bättre - skapa en metod som gör endast det - skickar en get-förfrågan med alla variabler - och anropa den närhelst jag behöver rendera om. (och jag kan till och med ta bort dessa rader från componentDidMount() istället för att skriva om raderna. Är detta rätt tillvägagångssätt?)

Jag har alltid trott att när något ändras i DOM (till exempel ordersBy-knapparnas :active-klass/stiländring) - uppdateras allt som kan uppdateras. Har jag förstått det rätt nu? Fel?

redigera: Oh, och om du ser något annat värt att nämna för att upplysa mig - var snäll och gör det.

    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;

Svar #1

Hur hämtar jag data (via GET) efter att viss React-tillstånd har uppdaterats?

Jag tror att du inte närmar dig detta korrekt, flödet bör vara:

  1. Användaråtgärd
  2. hämta data
  3. (i asynkron) statusuppdatering
  4. rendera

och inte tvärtom där en rendering utlöser en datahämtning.

Jag rekommenderar att du omprövar din komponentdesign istället för att försöka få det felaktiga flödet att fungera med din nuvarande implementation.

Se detta codesandbox för ett exempel: https://codesandbox.io/s/boring-matsumoto-ti9ot?file=/src/App.js

Redigera:

Från kommentaren nedan:

Hej Nick, jag har en annan fråga angående detta. Om jag beställer resultat via e-post (som återställer sidan till 1 och biljetterna till []), hur går jag från att klicka på ett filter till att hämta tillståndsuppdatering om jag behöver att tillståndet uppdateras innan jag hämtar data.

Igen, oroa dig inte för att manuellt tajma renderingar och uppdateringar, hantera bara ditt tillstånd och låt React hantera uppdateringar och renderingar, till exempel:

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>
  </>
);

För ditt användningsfall skulle du antingen bara visa data när laddningen är klar (vilket effektivt återställer data till []), eller visa någon form av platshållare tills datan renderas. Istället för att sätta tillstånden till tomma, sedan hämta, och sedan sätta tillstånden igen.