DEV Community

Cover image for React just got awesome'er!
Sayan Mondal
Sayan Mondal

Posted on

React just got awesome'er!

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


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

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

}
Enter fullscreen mode Exit fullscreen mode

A better way

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

}
Enter fullscreen mode Exit fullscreen mode

The proposed way

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

}
Enter fullscreen mode Exit fullscreen mode

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. ✌🏼

Top comments (2)

Collapse
 
sunilhurkadli profile image
Sunil Hurkadli

Hi Sayan, its been while i am searching , can you suggest any chaos engineering tool which support Azure webapps and Azure Functions ...? any help would be highly appreciated

Collapse
 
sayanide profile image
Sayan Mondal

Hey Sunil, sure, there are quite a few options out there for Azure-based chaos. You can check out ChaosMesh (chaos-mesh.org/docs/simulate-azure...), LitmusChaos (hub.litmuschaos.io/azure/all-exper...) and also Steadybit (hub.steadybit.com/targets). Hope this helps.