π¨βπ» Github Repository
If you just want to take a peek at the code, here is a repository I used for the article.
π Premise of this article
The following content is purely experimental and by no means implies that it is "best-practice" or "this is how it should be done". I'm trying to become more familiar with React and these experiments help me see my own failings and misunderstandings of the framework.
π¬ Feedback
I love receiving feedback from this awesome community and learn so much from the advice or resources given.
Context API
The React ContextAPI was introduced, to my understanding, NOT to replace state management, but rather, easily share props down the component tree. This made the ContextAPI a great way to avoid the "prop-drilling" problem. If you'd like to know more about that, I can highly recommend the blog post on prop drilling by Kent C. Dodds.
π§ͺ The Experiment
Given the design of the ContextAPI, I thought, perhaps it COULD be used for sharing and updating state. The ContextAPI has a Provider that can be wrapped around any component, to expose the data you'd like to pass down the component tree.
If you're interested in seeing what i came up with, please read on. π
1. Setting up the AppContext
The first order of business, was to create a Component that I could wrap around my App. This Component should be the Context Provider where I can share my state and a function to update the state from anywhere in the app.
This allowed me to easily wrap the AppProvider
component around my entire app, as seen below.
2. Reading state using a Custom Hook
Although the above worked okay, trying to update or even read the state felt very cumbersome.
The component would need to get the entire state object out of the Provider and then use state.propName
when reading from the state object.
Therefor, I created a custom hook called useAppState
that accepted a reducer function to get a specific state property from the state object.
This allowed me to use the following code to read any property from my state object.
If I need to get multiple items from state I could simply destructure from the entire state object, or write multiple lines to get the property I need.
I've noticed that using multiple-lines does create a duplicate AppContext object in the React developer tools. Every component that uses this function seems to get a duplicate Hook entry under hooks
Although, I'm not sure if this is only a visual indication or if the state objects are actually duplicated in the component. See below:
3. Dispatch function to update state
The next step was to improve the developer experience when updating the state. Even though the set state worked fine, it wasn't a great experience having to destructure form the AppContext and constantly having provide the current state and the new state.
After making the above changes, I could now easily get the dispatch function from the AppContext using the Custom Hook.
As an example, if I wanted to update the profile, I could do use something like this:
The above code shows that you can simply pass in an object with the properties relating to the state you'd like to update.
Any component that uses the useAppState
hook would also be re-rendered with the updated state.
Edit: 21.05.2021 π This behaviour could also be a caveat of the solution. As pointed out by @dikamilo in the comments, ANY component that uses the
useAppState
will reload. This severely limits app scalability.
End Edit
You can now also, quite easily, update multiple state values using this pattern:
...
dispatch({
movies: response.data,
uiLoading: false,
});
This is the basis of the idea. You can of course do a lot more to optimise and improve the code.
π Findings
I found that the lack of debugging tools makes this a poor choice for real-world applications. If you would like to make a small prototype, or a simple app that has very little state, the approach could work fine. Beyond that I can't say that this would be a great development experience due to the lack of debugging.
You can track the state in the React DevTools.
I would however not consider using this as a solution above established state management tools already available.
Have you ever tried something like this before? Do you have a better approach. Feel free to add comments or insights you might have!
Top comments (2)
As you're mentioned, any component that uses
useAppState
will be re-rendered when state changes, and this is because you're grouped all state object into single Context. This may be a big drawback in application, so you're may consider splitting state into multiple Contexts.Sometimes separate state solution is too big gun for the problem, when you're having a little state to manage in application and Context API may resolve this problem.
And if you keep data from the backend in your global store, you may consider to use for example react-query that will cache your data without global store.
Yeah, that is one major drawback for this approach! Iβve only used Redux as a state management solution. Iβll certainly look into react-query.