React Madness

Published on: Thu Aug 11 2022

Meta Frameworks

So you want to use React, but with what? There are plenty of options to choose from:

Right off the bat: please do not use CRA. It is outdated and worse than all of the other options.

Also, if you do have the option, do not use Webpack. Just don’t. There is no reason not to use a more modern alternative, such as Vite or Snowpack.

So let’s get to the ones, that you should actually consider.


First up we’ve got Astro. The case for Astro is pretty simple: If your site is not very dynamic and does not have too much interaction on the client going on, it’s a very good choice. A portfolio site, blog or landing page - all of these are examples where Astro makes a lot of sense. Just don’t build an Admin Panel with it, you would not enjoy it.


Next up: Remix. Remix is relatively new to the block. It has only recently been open sourced by Vercel and wants to enhance the web experience for the developer and the user. It blurs the line between client and server, by giving you the ability to write your server and client code in the same file and connect them seemlessly. Take this as an example:

export async function loader({ request }) {
  return getProjects();

export default function Projects() {
  const projects = useLoaderData();

  return (
      { => (
        <Link to={project.slug}>{project.title}</Link>

The code inside of loader will be executed on the server and useLoaderData will fetch that data on the client without you having to provide or write an API as a middleman. Remix not only handles the server->client dataflow, but also allows for very easy data mutation to reach the server with the help of good old HTML Forms. Remix still does a lot more regarding error handling, preventing waterfalls, improving loadtimes, … but all in all Remix is a solid Framework that is best used, for more dynamic sites, where Astro might reach its limits in terms of DX. Maybe an admin panel, a blog with comment and subscription features, a landing page with a contact form, a CRUD application with limited complexity.


Now let’s get to everyone’s favorite: NextJS. NextJS has been around for a long time and even calls itself “The React Framework for Production”. And for good reasons. If you are building a serious web application with a lot of dynamic elements, a database, more complex logic than just CRUD, edge functions, SSR and so on, NextJS is the perfect candidate. Sure, you could go more low level with Vite and implement SSR, routing and edge functions yourself, but there is really no good reason to, if you eventually want to push something to production in your lifetime.


The other options are usually only relevant when you really know what you’re doing. This might be when you don’t want to host a NextJS application on Vercel, but AWS, in which case you won’t be able to use a lot of the features that NextJS offers with the help of Vercels infrastructure.

Another one might be that you would like to use a very specific combination of tools (like routing or backend libraries) that are difficult to integrate into existing frameworks such as NextJS or Remix.

Here’s a good article of a company that moved away from NextJS that goes into the reasons and journey: Moving away from NextJS


Here I want to address Preact. A “fast 3kB alternative to React with the same modern API”.

The situations where you want to choose Preact over React are quite straight forward:

1. You are using Astro.

If you are using Astro, you might aswell use Preact. Astro already produces very light websites, and loading megabytes of React would just be a waste of Astro’s efficiency.

2. You are using Vite (or another build tool) and need speed

If you find yourself building a website that needs to work and load very fast while handling a huge amount of data, React sometimes just doesn’t cut it (even optimized with useCallback’s and useMemo’s). In that case, just swap it out for Preact and see how much more performant your site will get.

State Management

If you’re building something with NextJS, Remix or Vite and are unsure how to connect your API and server to your client, you have probably stumbled across the dozens of options you may choose from. And by dozens, I really do mean dozens. Here are a couple of ones that we are not going to cover, but you can look into, if you are interested:

These are the libraries that we are going to talk about and that should cover 99% of your use cases:

But first off, let’s define what we need by state. By state we refer to data, that usually changes frequently. We are concerned with 2 different types of state: client and server state. Server state is everything that exists outside of our client. User data, login information, everything that is inside of a database. Client state is concerned with navigation state, open/close state of the menu, opening modals, form inputs, etc.

So let’s get into our 5 state management solutions:

The only server state you will need

4 of our 5 state managers are concerned with client state. The only server state manager you will probably need is React Query. It makes it super straight forward to synchronize data between client and server. You can fetch, refetch, invalidate queries and mutate data in a very reactish way.

The client

Now let’s work our way up the complexity ladder with client side state.

The most simple form of state you can use in React is through the useState hook. It is confined to the React component you are calling it in and usually serves to bind data to form inputs or set temporary filters. If you can, use useState. The moment you realize you need that data to be available somewhere else, we’ve got you covered…

… with jotai. Jotai is great, if you need global state. Think of it as a global useState. It’s great if you need to toggle your navigation menu, toggle between light/dark theme or reuse device and browser information. There’s really not much more to be said about it.

Now if you need to interact with that data in a more complex way than just setX(Y), Zustand is a great state manager. It has got events, actions and stores. You can also compose stores and have stores with very specific use cases. And interaction between them is just as easy. To be honest, it’s just pure bliss using this library, especially in combination with React Query.

As a last restort, if find that you are reaching the limits of Zustand and your state machine is so complex you need a diagram to visualize all of the states, inputs and outputs it should handle, look no further than XState. To be honest, I can’t even think of an example from my own work where I would’ve needed it, but that doesn’t mean there aren’t any out there.

About React Context

React Context is often overhyped and overused. I would only recommend it if you’re finding yourself prop drilling more than 3/4 levels deep and want to simplify your code. The danger of context is that it does not check for atomic changes in the data that you are sharing. So if you are sharing a user object and a component uses it to react to a specific property, it will react to all changes to that object and rerender everytime anything changes in that user object. And not just when the specific property of that object has updated.

Mix it up

Do not think that you need the one state manager. You can use multiple along side each other with no problems. Use React Query to fetch data from the server. Use jotai to manage your menu state. Use Zustand for providing actions to do with the data you just got from the server and useState for all of your form inputs.

It’s not a competition. It’s about using the right tool for the job.


By now you probably realized that React is complicated. It is a very powerful tool with a huge ecosystem. Which is great but at times overwhelming.

Using the right framework and the right tool for the right task is very important and taking the time to evaluate your options is worth it, even if you’re just building a silly side project.