In your code, one very common scenario you want to account for is the need to check for response.ok (and potentially other response codes if you'd like to get more granular) and then handle it appropriately if you do not get the response.ok.
I handled it below in the code snippets and as you can see, the chained .then statements keep the error statements within the particular "steps" of the chain. In the async/await, the checks/response handling are within the main try block. As you can see from the code, the handling of these edge cases are so similar that at the end of the day this becomes a matter of preference.
// Method 1 useEffect(() => { const response = fetch('/api/tacos', { method: 'GET', headers: { 'Content-Type': 'application/json', }, }) .then((response) =>{ // ** CHECK AND HANDLE VARIOUS RESPONSES if (response.ok) { return response.json(); } else { throw new Error('Response NOT okay');} }) .then(({ data }) => { console.log('Success:', data); setTacosArray(() => data); }) .catch((error) => { console.error('Error:', error); }); }, []); //Method 2 useEffect(() => { const fetchData = async () => { try { const response = await fetch('/api/tacos', { method: 'GET', headers: { 'Content-Type': 'application/json', }, }); // ** CHECK AND HANDLE VARIOUS RESPONSES if (response.ok) { const { data } = await response.json(); console.log('Success:', data); setTacosArray(() => data); } else { console.log('Response NOT okay') } } catch (error) { console.error('error', error); } };
However, these types of issues may not be the big picture of what side effects or issues may come up with data-fetching.
Most web frameworks are not very opinionated in terms of fetching/updating data and React is one of these frameworks. NextJS is more opinionated and has become more opinionated over the years ... it has the library swr, had created various methods including getStaticProps, getServerSideProps, Incremental Static Regeneration each with it's own caching and retrieval mechanism, and in NextJSv13.4+ there was an overhaul of the routing system, a move to use core WebAPI res/req objects instead of res/req node objects, and has introduced various default caching mechanisms across the board.
The meta point here is this ... you asked about chaining .this statements vs. async/await to ferret out what are the issues that can arise down the road as the app becomes more complex and how can you "future proof" the code. Well, the short answer is that the either way you do it, whatever issues that come up can be similarly handled with the .then or the async/await.
Now, from you question, I think you were trying to get a glimpse at what the bigger issues at play are here. And these issues go beyond the useEffect/fetch/.then vs. async/await but it is related to the synchronization of data between client and server which is essentially what your code handles. (The following is paraphrased from the TanStack Query AKA React Query docs.). Client state and server state are different. Most statement management libraries handle local state well but do not do as well with async/server state. This is due to the following reasons. Server state:
- Is persisted remotely in a location you do not control or own
- Requires asynchronous APIs for fetching and updating
- Implies shared ownership and can be changed by other people without your knowledge
- Can potentially become "out of date" in your applications if you're not careful
And then the synchronization between client state and server state brings up these issues:
- Caching... (possibly the hardest thing to do in programming)
- Deduping multiple requests for the same data into a single request
- Updating "out of date" data in the background
- Knowing when data is "out of date"
- Reflecting updates to data as quickly as possible
- Performance optimizations like pagination and lazy loading data
- Managing memory and garbage collection of server state
- Memoizing query results with structural sharing
Long story short, either method you asked about in your question (.then vs async/await) is fine for what you are doing as specified by the code in your question.
When you want to do more optimizations, handle things like pagination, and have more control of automatic updates ... then you can turn to a library like TanStack Query.
Read more on TanStack Query AKA React Query here.