简体   繁体   中英

What is the sequence of actions when using promises in useEffect hook in React?

In the code below I was expecting that inside the useEffect hook console.log procedure will log the list of the tickets fetched by getAllTickets function because list of the tickets is returned without error.However console.log results in logging an empty array that I set up in the state initially. It seems that console.log is somehow preceding the fetch process and following setTickets hook. Could someone help to clarify this confusion?

import ReactDOM from 'react-dom';
import * as React from 'react';

import { getAllTickets } from './api';

const App = () => {
  const [tickets, setTickets] = React.useState([]);
  

  React.useEffect(() => {
    getAllTickets()
      .then((res) => setTickets([...res]))
      .then(() => console.log(tickets))
      .catch((e) => console.log(e));
  }, []);

  const renderTickets = tickets.map((t) => (
    <div key={t.id}>
      <p>{t.description}</p>
    </div>
  ));

  return (
    <div>
      {renderTickets}
      <button onClick={() => setOpen(true)}>Add ticket</button>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));

getAllTickets fetches list of tickets from db as below

export const getAllTickets = async () => {
  const res = await fetch('http://localhost:3001/tickets');
  const data = await res.json();
  console.log(data);
  return data;
};

It's not that there's a sequencing issue. It's that the function logging the tickets value is logging an old value.

Your useEffect callback is created each time your component function is called, but because your dependency array is empty, only the first of those functions is ever called by useEffect . That first function closes over the tickets constant for the call to your component function that created the callback (the first call), in which tickets is an empty array. So although setTickets updates your state item, which will cause your component function to be called again, your useEffect callback (or more accurately, the callbacks it creates) continue to use the old value.

If you want to see the updated array, you can use res :

React.useEffect(() => {
  getAllTickets()
    .then((res) => {
          const ticketsReceived = [...res]; // Why the shallow copy?
          setTickets(ticketsReceived);
          console.log(ticketsReceived);
     })
    .catch((e) => console.log(e));
}, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM