React just got awesome'er!
Tags: react, webdev, javascript, typescript
Published: 2022-10-21 10:31:05

> TL;DR -- React introduced the `use` hook and converted all its components into server first, which suspends your components until the promise/s has been resolved resulting in a much cleaner UI and no janky loading states.

If you've ever worked on a React or Next.js application, you've probably noticed that it's pretty un-opinionated in general, particularly when it comes to dealing with asynchronous behaviours. However, the initial Server Components proposal made it difficult to access promise-based APIs.

React has **finally** acknowledged that async is an important part of developing applications on the web. Instead of having multiple useEffects or useSWRs and a ginormous loading hell, React finally decided to provide a seamless integration to resolve promises by wrapping them in special bindings. Which is exactly what this article tends to talk about. So sit tight and lets get reacting!

---

## Proposal

Adds first class support for reading the result of a JavaScript Promise using Suspense:

* Introduces support for async/await in Server Components. Write Server Components using standard JavaScript await syntax by defining your component as an async function.

* Introduces the `use` Hook. Like `await`, `use` unwraps the value of a promise, but it can be used inside normal components and Hooks, including on the client.

> Read the full proposal here: [First class support for promises and async/await](https://github.com/reactjs/rfcs/pull/229)

---

## What does this mean for us?

In a typical React application we would have components that are dependent on some data to be fetched and while that is done we usually go with a loading state which renders a spinner while our promise isn't resolved, the child components also might have their own data fetching which would also require to be resolved, and thus a very janky UI.

Within React, we can leverage Suspense boundaries and have a tree of components that are all calling data, which needs to resolve promises at individual levels. We can just suspend at the top and let all of the promises below it resolve themselves, resulting in no more interruptions or flaky loading states.

With a significant change like this, React also announced that all its components are now server first by default until you choose for it to not be. You might be thinking now, what about `react-query` our good old friend, well it helps us remove redundant local states we no longer need by leveraging API states instead, but it also returns a loading state, which no matter how optimised still doesn't keep us from defining the endpoint on the server.

---

## The old vanilla way

```typescript
// Vanilla.tsx

interface IData {
  author: string;
}

const getData = async () => {
  return await fetch("/api/endpoint").then(res => res.json());
}

const Vanilla: React.FC = () => {
  // Old way of maintaining a state to update it once the data is fetched
  const [data, setData] = React.useState<IData | undefined>()

  React.useEffect(() => {
    getData().then(data => setData(data))
  }, [])

  // Check if data is undefined then handle loading state
  if(!data) return <Spinner>Loading...</Spinner>

  return (
    <div>
      Data has been rendered: {data?.author}
    </div>
  )

}
```

## A better way

```typescript
// ReactQueryWay.tsx

const getData = async () => {
  return await fetch("/api/endpoint").then(res => res.json());
}

const Better: React.FC = () => {
  // No more local state to maintain the data, instead use API states
  const {data: fetchedData, loading} = useQuery(["example"], getData)

  // Check if loading is true then handle loading state
  if(loading) return <Spinner>Loading...</Spinner>

  return (
    <div>
      Data has been rendered: {data?.author}
    </div>
  )

}
```

## The proposed way

```typescript
// TheUseWay.tsx

// Making the component async and turning it into a server component
const Current: React.FC = async () => {

  const data = use(await fetch("/api/endpoint").then(res => res.json()));

  // We don't need to check for loading anymore because the state is defined, the `use` hook would suspend the component altogether till the data is not returned
  return (
    <div>
      Data has been rendered: {data.author}
    </div>
  )

}
```

---

## Conclusion

If I missed out on any point or you want to discuss something feel free to leave a comment down below, I'd hop in ASAP. 🌟

Lastly, Thank you for making it this far down into the article and showing your interest in React. You are amazing and keep making a positive difference every day. Peace out. ✌🏼