New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] New dependency: Easy Peasy State Management #3442
Comments
I don't know if this was discussed or needed or whatever, but I think it's nice to keep our tools fresh. Besides easy-peasy, I've used https://redux-toolkit.js.org/api/createSlice which is a breath of fresh air after "regular" redux. It makes handling redux way easier, so I'd like to nominate that as one of the alternatives, but why do we need redux? |
Because we have a sophisitcated application, and rather than rewriting state managment every time we need manage state we can look at things that the team has worked with in the past, things that have a vibrant, healthy ecosystem and a good track record at scale. However, I would like to focus the question on: why easy-peasy? That's the point of this RFC. There are plenty of "why redux" articles online and some inherent bias I'd like to combat. The end user doesn't even need to know that redux is below, unless they would like to tap into the middleware ecosystem and add something like 1-line-of-code localStorage persistence, for example. Dive into the easy-peasy docs to learn more. More specifically to product needs, this came up in response to a pretty massive app we're about to undertake on consignments that has a lot of global state, and we have a good opportunity to establish some patterns here: |
Something that's unclear to me is the relationship between state and routes. My feeling is that Formik can handle the state on the forms and routes can implicitly handle the state of which thing to show. I'm still struggling to see which bits of state easy-peasy will help with. |
Formik will indeed handle form state, but we will need to coordinate things from a higher point of view; for example, locking and unlocking route navigation, saving and restoring form state, and in general thinking about things from a global top down perspective via an orderly action-based flow that genericises execution across a very wide component tree. Sophisticated user flows in particular benefit from top-down thinking. In addition, this is an opportunity to establish some state patterns going forward for other work in Eigen (and elsewhere) in an attempt to coral some our custom React.createContext usage in favor of something that's simpler, consistent and also more performant. |
Is the idea of this proposal that we would use There is complexity in redux-based solutions, and a learning curve for the team - it's a different way of thinking. The benefits it brings are not free. Having managed apps that were built entirely on redux for state management, my experience was that the amazing debugg-ability you get from redux tools was often only necessary because of the fact that state management had become so much more complex. |
@pepopowitz - This RFC is for |
Thanks for the details Chris. I think using easy-peasy makes sense in the abstract, though I do share some questions from Jon about how specifically it would be helpful. Eigen doesn't really have a lot of global state to manage in between most screens; while this new Sell app might be an exception, adding any dependency beyond React would increase the barrier to entry for engineers contributing to that code. As Steve said, these abstractions do have a cost, and I want to be sensitive to it in the long run. To help me understand where easy-peasy will help us, could you give an example from the Figma designs where easy-peasy would help manage state? I know React Context isn't an ideal API, but I'm curious about comparing how it would work in that example. |
I guess where I'm landing on this is that I'm not convinced we have a situation where the use of easy peasy is warranted. I'm not saying that easy peasy isn't a great lib, just that while spiking and tinkering with this project I have not seen problems for which it is required. |
This isn't about just managing state across screens, its about intra-component-tree communication. Doing a search in Eigen, there's twelve uses of
It's not that its not ideal, it's that it's a primitive that provides no API requiring devs to create their own each time its used, which in turn increases complexity across the app. It also requires that we manage performance on our own, versus intelligent (invisible) optimizations built in at the library level.
It's about orderly control flow. Mentioned above:
Is the form complete? Check. Navigation is unlocked. Back button press? Are you sure? Dispatch action to show confirm? Confirm. Dispatch action to navigate. I can continue elaborating. All of these things sit centralized in one location and conform to a consistent API outside of the component callee. This improves long-term maintainabiliity. This stuff could be moved into Additionally, |
Okay, thanks for elaborating. I'm just trying to make sure I understand the trade-offs here. We have had a conservative policy around adding new iOS dependencies for several years and it's helped us prevent what happened in the native side of the app: multiple dependencies to do the exact same thing, because the team didn't communicate&socialize the benefits/capabilities of new dependencies. I'm not saying easy-peasy is a bad solution – it sounds like a nice library, actually! I just want to make sure that I understand its value and tradeoffs because my team will be responsible for it in the long term. Am I making sense? |
That makes sense! When we write If it helps, after this My Collections work calms I'd be happy to volunteer some migration work around our existing usage, too, and further evangelize. @ds300 might have some thoughts here as well. |
Aside from this new Consignments work, we'll need to implement a global app state for auth, lab options, etc, as soon as we take the plunge on Android in Q3. I think easy-peasy would be a perfect fit for that. Its 'batteries-included redux' approach seems great to me. It solves most of the problems I had with redux back in 2016-2017 and then some, and I'm confident it would provide a very robust foundation for building state-heavy features going forward. I see no reason not to adopt it. In retrospect I kinda wish I had suggested it to @ashleyjelks back when she started working on the collection filters since she ended up having to reinvent certain patterns not provided by useReducer that easy-peasy makes... well... easy-peasy. |
I think it will be a good addition, and like you say Chris. My initial concern was I guess me being afraid of having it "too easy" to just use easy-peasy/redux for all kinds of state management. I think with relay, things are pretty alright. I agree the Context parts would become easier, I'm all for it. I just want to make sure or be clear that we will not start mixing these two willy-nilly until we end up with a tangled mess of data living in random places and getting fetched from all over the place, and having to manage that. If we stick to using easy-peasy/redux for the purposes of managing state, as in flows, (navigation, notifications, consistent and common api for all our stuff, basically something more like a state machine) rather than state, as in data, (fetched data etc) then merge this already 😅. |
Okay, thanks for the discussion so far everyone! Here's a recap of what I have learned:
Therefore, I think:
Are there any other questions/concerns anyone has? This is the exact right time to bring them up 🙌 |
+10000000 (also, I'd like to be there too) |
Some further discussion of how easy-peasy vs another approach compare here: #3451 (comment). |
I was thinking the same thing, that that's a great first place. I think the LOC count will nicely condense too. |
agreed. refactoring the filters would be a great place to start since the architecture is so similar! |
As I was reading this I was also going to suggest the filters as a place that could have benefitted from a library like easy-peasy! Happy to help out with that migration, sounds fun. 😄 I don't have too much to add but it will certainly be nice to have a preference when the need does arise (which it certainly will) for more complex state management. Easy-peasy seems like a good choice! |
In most instances |
Right, I should have specified shared state. That makes sense to me. Are there any circumstances that we might want to use contexts instead? |
I would imagine a context being used in a situation that may grow into a library that can be extracted from eigen where we'd want to keep the external dependency count low. (Though even in that case, personally, I'd rather use a proper state management solution than roll my own.) Mentioned above, every time All of this is to say, in my ideal gate-keeper world I would see |
Very much agree 👍 Damon mentioned at his last gig they were storing their Apollo store in Redux creating a real mess of things. That's an architectural design problem that could manifest in any number of ways, and has nothing to do with shared state management in principle. Relay is Relay and shared state is shared state. (And in any case, Relay has its own global context / store that one can acess from anywhere.) It will be up to the team to catch issues like this in code review. |
Closing with We'll be using this first in the incoming MyCollection Eigen app and then migrating collection filters over to the new setup. Thanks everyone for your input 👍 |
ResolutionWe decided to do it. Level of Support3: Majority acceptance, with conflicting feedback. Additional Context:Some people were in favor of it, but others felt that a library that used redux might be overkill. Next StepsBeing implemented in the new MyCollection app in Eigen. Collection filters will be refactored. ExceptionsNo exceptions. |
New Dependency
Name:
easy-peasy
URL: https://github.com/ctrlplusb/easy-peasy
Focus
Easy Peasy is a popular state management solution built on battle tested redux. It provides a modern API and comes with everything one needs to quickly manage inter-component state without needing to write everything from scratch. It has first class TypeScript support, gives us access to the redux middleware system, comes with an immer-based state update patterns, and proves some excellent (and simple) abstractions around observing actions within a system and acting on them without having to write mountains of glue code.
Example from docs:
Going forward Eigen would benefit from a consistent, hooks-based batteries-included state management pattern.
Check List
Alternatives
There are quite a few alternatives in the react state management space. We could use redux directly, but the common complaint is that it's too verbose. We could also use react's context directly, but that would mean a lack of consistency, needing to hand-roll perf optimizations, no middleware, etc.
The text was updated successfully, but these errors were encountered: