State Management - HausDAO/daohaus-monorepo-deprecated GitHub Wiki
Overview
Application state is a core challenge we investigated when considering the v3 architecture. We spent time evaluating our lessons learned coming out of v2 and its Context-based approach to state management as well as v3's architectural needs. Since v3 is split into several modular apps, we have the opportunity to evaluate state on an app-by-app basis. This allows us the opportunity to make a decision that is driven by the problems that each app is solving, and provides us with the freedom to experiment with approaches.
One of the core decisions we find ourselves facing is whether or not we need to leverage a state management library such as Redux or if we're able to use React hook solutions such as context, state, and reducers.
To Redux or Not: When to Choose Redux
When looking at our apps, we initially asked the following questions:
- How often will our state change?
- Will our state mainly update in chunks based on actions such as polling?
- How would complex queries for things such as proposals change things, and where would we want this to live? Would Redux help here?
We'll be evaluating our state needs for each app. We referenced the When Should I Use Redux? section of the Redux docs and evaluated each bullet point listed below:
- "You have large amounts of application state that are needed in many places in the app"
- "The app state is updated frequently"
- "The logic to update that state may be complex"
- "The app has a medium or large-sized codebase, and might be worked on by many people"
- "You need to see how that state is being updated over time"
We've turned this list into a rubric where we evaluate our state needs for each app as it's being architected and revisiting if state needs change to meet these criteria. In general, we're aiming to reach for context first and then add in Redux when it makes sense.
Additionally, we've seen that Redux makes the most sense when working with "high write" applications where lots of data is being written that can impact the application state.
[to be continued]
Digging Deeper
This section is our raw notes from our discussion thread and conversations:
- Context is great for "low write, high read" since it triggers when things are updated
- Redux is better for "higher write" use cases
- If we don't see many "high write" use cases we could reach for redux
- Can we set a framework for when we'd want to bring in Redux (to manage a high write usecase)?
- What would this look like?
- When should I use Redux?
- We do have a lot of state throughout the app, but less true for v3 than for v2
- SDK resolves a lot of this since state stays up to date (especially with regards to pagination)
- Instead of having to serve all data across the entire app, we're able to be more selective and we have better tools for managing state
- How often is our state updated?
- Seems to be pretty infrequent due to how slowly DAOs update
- What is our criteria for deciding to move to Redux?
- We're talking about this for Core UI (most likely, at least)
- We saw the problems of relying on Context in v2 and we'll need to be aware of this threshold in v3 and this'll determine where and when to reach for Redux
- If Core UI starts to get messy we can then reach for Redux
- As things are being architected we could even make the decision early on if we start seeing some of the criteria being hit
Feature Packages
- Distributing state across packages such as DAOhaus Connect, theme state, etc.
- Distributed stores -- how does this work with Redux?
- One Redux store per app -- working with a single store still works with this approach
Approach 1: Layering in Context
- Sprinkle in different Contexts as needed in a modular way
- What if we have to pivot on a moments notice? Would having modular Contexts work?
- Can do this with Redux as well
- Modular Redux:
- Don't need multiple stores -- can put the state at different points within the single store
- Initialization functions add in the reducers into the single store
- Still composable -- don't need multiple stores (whereas flux is multiple stores)
- Con:
- Dependencies across contexts isn't always straight forward, so when state is updated it's not always clear what the dependencies are
- How would everything come together and integrate if we decide we need to use Redux?
- Redux store is another Context provider in a certain way -- so we wouldn't necessarily be crossing between Context and Redux
- We'd have to do this through composition within the different components
- Framework link: https://redux.js.org/faq/general