React Context, async calls with hooks, Redux like architecture and combine context providers with Typescript

image used from https://www.robinwieruch.de/static/dbb6b6b256b589aad81a3ed374590f4d/2b1a3/banner.jpg

We have a simple task here, we need to implement state management with React Context, handle some async calls, do so while sticking to redux concepts, and at the end combine everything in a single-store provider.

Let’s say that for example, we have a web app, that has some user authentication, some website configuration and of course error handling.

Overall architecture and principles

We want to achieve that components are free of async calls, that state is changed through reducers and that we combine providers so code is cleaner and easier to reason about.

Folder structure

Displaying Errors

context/error/types.ts

context/error/actions.ts

context/error/reducer.ts

User authentication

context/auth/types.ts

context/auth/actions.ts

context/auth/reducer.ts

Now we want to extract dispatch from the components, the component itself should not be aware of how we are handling actions it should just consume context without worrying about its internal implementation. this easy to do, and in my opinion, it really helps to separate concerns between our application layers. Let’s start with the error context.

context/error/index.ts

And now we just need to consume ErrorContext in ErrorBanner component.

This was easy since the logic is pretty straight forward, just setting and clearing errors, but what about auth there we have an Http calls and possible errors, let us see how to approach that problem.

But before we do that I would love to take a quick break and talk about HTTP requests from our app to external services.
At this point, we already can deduct that if you want to do it right you do it with function, even better higher-order function, but why? Let me explain, the advantage of doing this with custom hooks (HOFs) is not just writing code with hooks since that is hot in the community, one of the most important things is that in your functions that are written as hooks you have access to context, and that is really cool and allows you to do so much more than you think. So let’s create our general hook for HTTP calls.

useHttp.ts

Wow! we can set and clear errors on every HTTP request without having to worry about that in inner layers, that is pretty cool. Let’s now create specialization of this general hook so we can tackle specific problems.

We have auth Http calls so we are gonna create useAuthHttp hook.

useAuthHttp.ts

As you can see here we don’t have to worry about failing requests, here we only worry about auth token in the response.

We can now continue with our work on the auth context.

context/auth/index.ts

Login.tsx (I will not focus on validation and etc this is just for sake of story context. If you are interested in that you can read more in the story below)

Configuration
So here is the same old we have types, actions, reducer, context, useConfigHttp for Http requests, so no need to go throw that, for sake of rest of the story.

Combining Context Providers
This is nicer to have, this is not necessary, but I think that this is one of those things that you must have if you have multiple context providers that some components need to consume. We just need to look at Context Providers as they are, just React components.

combineComponents.tsx

I know this might seem confusing but we are just stacking components as wrapper here. Stay with me you will see benefit soon I promise.

Let’s finally create a combined context provider and provide it in our app index.tsx as we will do with redux.

store/index.tsx

What is important here is to be aware of providers dependencies if you have any, we have a dependency on useHttp hook on ErrorContext and as we use that hook in both Auth and Configuration contexts we need to provide ErrorContextProvider before his dependents.

src/index.tsx

And that is that we can now consume our context anywhere in our app. This are the principles that you can apply to develop large scale applications with redux like architecture.

Highly motivated, dedicated developer. I’m also a functional programming enthusiast and that is something that I’m exploring in the last couple of years.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store