DEV Community

Discussion on: Do you need a State Management Library?

Collapse
 
sgoulas profile image
sgoulas • Edited

Context API is not a state management tool, neither it provides the benefits of one. It also forces rerenders across your application, degrading its performance. It should be used only for specific variables that you know beforehand they are not going to change often.

Collapse
 
link2twenty profile image
Andrew Bone

Which benefits are missing? Rerenders only happen for components that use the specific context that has a change. I generally have a different context for each dataset but try to have as few contexts as possible, this keeps rerenders to a minimum.

Collapse
 
sgoulas profile image
sgoulas • Edited

A state management solution stores a value itself. Context does not store a value, it merely provides a point of access for said value. The parent component that provides the context to the children is the one responsible for "storing" the value. Context also does not provide any mechanism for handling side effects. If you want to handle a login authentication flow with classic state management tools you have thunks, observables, sagas etc. Context does not handle side effects. Context also does not offer time travelling debugging. At any given point you can not deterministitcally know how the value passed by context came to be, whereas with state management tools you can inspect the sequence of dispatched actions.

Also, on the topic of multiple contexts, I can't speak without checking an actual example (the one provided in the post uses a single context provider), but the moment the application becomes a little bigger, sustaining a large number of different contexts becomes an impossible task. You have to juggle between what provider wraps what part of the component tree and then be specific in how you consume the provided value in that part of the tree. The moment you want a component to access a context value that was not previously available to it you have to restructure your provider wrappers to accomodate for this change. And this brings me to my final point, application wide state management solutions mean that all the reducers listen to all the dispatched actions, they just don't match actions for which they don't have a corresponding case. This means that at any given point a component connected to the redux store can dispatch an existing action and trigger a change in the application wide state. You can't do that with context because you have to be constantly aware of the whole structure so that a component can be inside the specific wrapper tree it needs to be. And of course, just as I mentioned earlier, even then, the value is not stored in the store, it's stored in a parent component.

You can also read a post by acemarke, a redux maintainer and one of the creators behind redux toolkit explaining in much greater detail why context is not a substiture for redux, their differences and their respective use cases:

blog.isquaredsoftware.com/2021/01/...

Thread Thread
 
link2twenty profile image
Andrew Bone

Yes, I know context isn't a state management solution hence saying

When we use this API in tandem with a custom hook it gets a lot more powerful.

But I don't really know what more you need other than global state. There are different ways to interact with state, like dispatching, but any of these can be coded into your hook and a just syntax sugar.

As for them getting to complex and hard to manage, this isn't a problem I've faced so far but one I understand.

Thank you for linking the blog post I'll give it a read 😀

Collapse
 
ash_grover profile image
Ash G

Rerenders only happen for components that use the specific context that has a change.

Careful here. If you're maintaining a global context, any change in any of the nested data in its branches will trigger a re-render because the reference to root object has changed. And all state management libraries rely on reference checks to determine if something has changed.

In other words, any non pure-component or a component not wrapped inside React.memo() which uses Context API via useContext() etc., will re-render anytime there's a change in the global state. Redux and other state management libraries prevent this re-rendering from happening with nested states which can improve performance.

In a non-trivial app, using a state management library with memoized components can give you huge performance gains. Especially in a mobile app where you have a lot of data to show.