From Redux to Zustand to Jotai to Zustand to Custom: Our State Management Horror Story

Rate this content
Bookmark

Our quest to make our product faster and more performant forced us to reevaluate our state management solution. Unfortunately more than once: in the span of two years we migrated from Redux to Zustand to Jotai then back to Zustand (this time with some fancy tricks) and then finally to a custom solution. 
Should you do the same to figure out which library fits your use case best? Is a custom solution really necessary? Probably not, and to prevent you from making the same mistakes we did I want to tell you what we found really matters, as well as some important things we learned during this painful journey.

This talk has been presented at React Day Berlin 2024, check out the latest edition of this React Conference.

FAQ

Plux is a web-based electrical CAD software that allows users to design circuits, electronics, schematics, and PCBs, along with creating connections and simulating circuits.

Plux is built using TypeScript, React, Three.js, and React 3.0 Fiber, with a codebase of about half a million lines of TypeScript.

The journey highlighted the importance of being open to migration and custom solutions when existing abstractions don't meet performance needs, and the value of learning from each change.

Plux initially used Redux for state management but experimented with Zustand and Jotai before creating a custom solution to better handle complex data and improve performance.

A custom solution was necessary to achieve granular subscriptions and improve performance, as existing libraries couldn't efficiently handle the complexity and scale of Plux's data and interactions.

Currently, Plux's custom solution is tailored to its specific needs and not open-sourced, but there are considerations to share insights or examples with interested parties.

Plux switched libraries to address challenges like supporting large documents, real-time interaction, multiplayer editing, and complex data dependencies, aiming to enhance performance and scalability.

The custom solution led to significant performance improvements, reducing interaction times from seconds to milliseconds by allowing precise subscription management.

Plux faced challenges in handling large documents with thousands of electronic parts, requiring efficient real-time user interaction and complex data processing, which led to multiple changes in state management approaches.

Plux identified performance issues through profiling, analyzing functions during interactions, and observing the time spent in listener stages and selector evaluations.

Giulio Zausa
Giulio Zausa
29 min
13 Dec, 2024

Comments

Sign in or register to post your comment.
Video Summary and Transcription
Today's Talk is about Plux, a TypeScript application built with React and Three.js. The speaker discusses the challenges they faced with state management and their journey of switching libraries multiple times. They started with Redux but later introduced GSDAN, a faster and easier-to-maintain state management library. They optimized performance using selectors but realized it became a problem when dealing with documents with many nodes. They replaced Zustand with Jotite for better performance but encountered limitations and ultimately implemented a custom store, resulting in a significant improvement. The speaker emphasizes the importance of not locking into a solution and shares their timeline for the changes. They also mention considerations for state management, recognizing performance issues, and the possibility of open-sourcing their solution.

1. Introduction to Plux and State Management

Short description:

Today, I want to tell you about how we did a bit of a horror story that we call it ourselves and about how we changed our state management infrastructure too many times. We're talking about this product called Plux, a TypeScript application built with React, Three.js, and React 3.0 Fiber. And one question that I heard a few times is, okay, React, but how are you handling state? And my answer to that is in a meme way, yes. We're using a bunch of different libraries and we switched them quite a few times.

Today, I want to tell you about how we did a bit of a horror story that we call it ourselves and about how we changed our state management infrastructure too many times. So let's get right into it.

What are we talking about? We're talking about this product here that I'm working on called Plux. And it's a very nice CAD, electrical CAD software for the web. Basically, you can design circuits, design electronics, the schematics, the PCB. It's like there is a lot going on and you can create connections and simulate circuits. It's cool.

And why are we talking about this here today? Well, because it's built on technologies that I guess that a lot of you know. It's a TypeScript application. We have like a half a million line of code of TypeScript and it's built with React, both the UI part and the 3D canvas part. It's built with Three.js and React 3.0 Fiber. So we are actually building on like a giant CAD tool on top of React 3.0 Fiber. And one question that I heard a few times from people that I talk to is, okay, React, but how are you handling state? Like are you using two standard Redux just hooks? What are you using? And my answer to that is in a meme way, yes. We're using a bunch of different libraries and we switched them quite a few times.

2. Switching Libraries and Introduction to Redux

Short description:

We switched libraries too many times due to the challenges of supporting enormous documents, real-time interaction, and complex cascading rules. Our goal was to run it at 60 frames per second on medium hardware. We started with Redux as our repository for persistent data, enabling automatic multiplayer and synchronization with the backend.

And why did we switch libraries too many times? Well, it was a bit of a discovery process. And this is because our product is quite challenging. We want to support enormous documents, which like 10,000 electronic parts, each one it's a 3D model with properties and stuff. And we want to support real-time interaction. So you can click and drag everything and the multiplayer, like what you do with the Figma and Google docs, you can just edit something and everyone else will see it. And we have a complex system of cascading rules, like every electronic component has dependencies between them. And we are running a bunch of computation in the background, like computing electrical properties, computing geometry, and that is all running in WebWorkers. And we have these kind of data pipeline because we are processing our data a lot before being able to show it to the users.

And there are weird dependencies between data and all of those challenges with the target of being able to run it at 60 frames per second on medium and hardware, which was incredibly difficult to do. So let's talk about the start. Where did we start with that management? Well, with Redux, of course, we love Redux. We still use it today. And the reason why we're using Redux is because it's our repository for persistent data. The entire document that comes from the server and then goes back to the server, it's persisted in Redux, which allows us to do something quite cool. We have automatic multiplayer and persistent and synchronization with the backend. Every time that we perform an action on Redux, everyone that everyone, every other person that is visiting that link will be able to receive it on their end. So that we don't have to take care of that, because every developer can just send the actions into Redux and it will automatically persisted and broadcasted. And we're doing that with the RxJS and Epix. But I don't want to get too much into that today because I want to tell you about the story of how we changed it.

QnA

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Query: It’s Time to Break up with your "Global State”!
React Summit Remote Edition 2020React Summit Remote Edition 2020
30 min
React Query: It’s Time to Break up with your "Global State”!
Top Content
Global state management and the challenges of placing server state in global state are discussed. React Query is introduced as a solution for handling asynchronous server state. The Talk demonstrates the process of extracting logic into custom hooks and fixing issues with state and fetching logic. Optimistic updates with mutation are showcased, along with the benefits of using React Query for data fetching and mutations. The future of global state management is discussed, along with user feedback on React Query. The Talk concludes with an invitation to explore React Query for server state management.
Managing React State: 10 Years of Lessons Learned
React Day Berlin 2023React Day Berlin 2023
16 min
Managing React State: 10 Years of Lessons Learned
Top Content
Watch video: Managing React State: 10 Years of Lessons Learned
This Talk focuses on effective React state management and lessons learned over the past 10 years. Key points include separating related state, utilizing UseReducer for protecting state and updating multiple pieces of state simultaneously, avoiding unnecessary state syncing with useEffect, using abstractions like React Query or SWR for fetching data, simplifying state management with custom hooks, and leveraging refs and third-party libraries for managing state. Additional resources and services are also provided for further learning and support.
Why You Should Use Redux in 2024
React Summit 2024React Summit 2024
33 min
Why You Should Use Redux in 2024
Top Content
Mark Erickson explains the history, creation, evolution, and benefits of Redux. Redux was designed to make state updates and action history maintenance easy, incorporating functional programming principles. Redux Toolkit was created to simplify Redux usage. Redux is still a valid choice for its consistent pattern and separation of state from UI. The decision to use Redux depends on the specific use case and the need for centralized state management.
Thinking in React Query
React Summit 2023React Summit 2023
22 min
Thinking in React Query
Top Content
Watch video: Thinking in React Query
React Query is not a data fetching library, but an Asian state manager. It helps keep data up to date and manage agent life cycles efficiently. React Query provides fine-grained subscriptions and allows for adjusting stale time to control data fetching behavior. Defining stale time and managing dependencies are important aspects of working with React Query. Using the URL as a state manager and Zustand for managing filters in React Query can be powerful.
Wait, React Is Multi-Threaded?
React Day Berlin 2022React Day Berlin 2022
22 min
Wait, React Is Multi-Threaded?
Top Content
This Talk explores the use of web workers in React to improve user experience and performance. It discusses the limitations of JavaScript rendering and how web workers can offload tasks to separate threads. The Talk also highlights the benefits of using concurrent mode in React and introduces the UseWebWorkerHook library for simplifying the creation of web workers. It emphasizes the considerations when using web workers and concludes with a mention of Postman's hiring and new feature release.

Workshops on related topic

Rethinking Server State with React Query
React Summit 2020React Summit 2020
96 min
Rethinking Server State with React Query
Top Content
Featured Workshop
Tanner Linsley
Tanner Linsley
The distinction between server state and client state in our applications might be a new concept for some, but it is very important to understand when delivering a top-notch user experience. Server state comes with unique problems that often sneak into our applications surprise like:
- Sharing Data across apps- Caching & Persistence- Deduping Requests- Background Updates- Managing “Stale” Data- Pagination & Incremental fetching- Memory & Garbage Collection- Optimistic Updates
Traditional “Global State” managers pretend these challenges don’t exist and this ultimately results in developers building their own on-the-fly attempts to mitigate them.
In this workshop, we will build an application that exposes these issues, allows us to understand them better, and finally turn them from challenges into features using a library designed for managing server-state called React Query.
By the end of the workshop, you will have a better understanding of server state, client state, syncing asynchronous data (mouthful, I know), and React Query.
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
React Summit 2023React Summit 2023
139 min
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
Top Content
WorkshopFree
Matteo Frana
Matteo Frana
- React Bricks: why we built it, what it is and how it works- Create a free account- Create a new project with Next.js and Tailwind- Explore the directory structure- Anatomy of a Brick- Create a new Brick (Text-Image)- Add a title and description with RichText visual editing- Add an Image with visual editing- Add Sidebar controls to edit props (padding and image side)- Nesting Bricks using the Repeater component- Create an Image gallery brick- Publish on Netlify or Vercel- Page Types and Custom fields- Access Page meta values- Internationalization- How to reuse content across pages: Stories and Embeds- How to create an E-commerce with Products’ data from an external database and landing pages created visually in React Bricks- Advanced enterprise features: flexible permissions, locked structure, custom visual components