Middleware Function for Reducer in Context API
In the Context API, reducer and initial state object are created to access or update the state values from the other components. Accordingly, the
useReducer hook is used for both getting state values and dispatching actions to update the values of the state provider. With the help of the
useReducer hook, actions for saving values into the state can be triggered easily from the components that are wrapped by the state provider. Before start reading this article it is important to know how the
useReducer hook works. Therefore, please visit here to get more information about useReducer hook.
In a normal scenario, what we do is create a context API to access its values from a deeper component. Let’s suppose that we wrapped our whole application with context and we want to do an HTTP request from a deeper component. We also want to send this request result to another completely different component. There are not even their child or parent components. Without context API, we can create callback functions and try to send this result to that component but it makes our codes complex and reduces the performance of the application. To optimize this data flow we can use ContextAPI. These are the benefits of ContextAPI. What if we need a middleware functionality to make another action each time a new action dispatch from a component. For example, you might want to trigger a logger method when a new action is dispatched. Without a middleware, we need to trigger it from the reducer or the component that creates the action. As another example, you might use the WebSocket connection to get data in real-time. Thanks to middleware functionality when a new message comes via WebSocket you can update the global state. Distinctly, you can do it inside the middle function instead of the react component itself.
In this article, I am going to explain how to apply a middleware function for
Context API and Reducer
First, let’s create a basic application with only one component. This component will be responsible for displaying messages and publishing messages to the WebSocket server. It will also have a button. When we click on the button it will send the “New message” string to WebSocket. The application will also listen to the messages that come from WebSocket and it will be handled in the middleware function.
Note: I am not going to create a WebSocket server, just assuming that there is only one.
We can start creating the reducer. I will name this reducer file as reducer.js inside the “src/” directory. There will be two state values as
sentMessages . We will keep messages whose sent by the user in
sentMessages and the messages that come through WebSocket will be stored in
As you can see from the code snippet above, there two action types defined to update the state value. The action of
UPDATE_SENT_MESSAGES updates the messages whose sent by the user with the given payload. The action of
UPDATE_RECEIVED_MESSAGES updates the messages that come through the WebSocket server.
To make this reducer usable in react components we need to create a provider. This is also where we should create middleware functionality.
reducerMiddleware wraps the
useReducerhook and returns the state and dispatch with the middleware function. It means that every action that has been dispatched by a function will first pass through the given middleware function.
useStateProvier is a hook that we can call every component for accessing state values and dispatch function.
Now, it’s time to create a middleware function. This middleware function will track the WebSocket messages and the actions dispatched in the components wrapped by the provider. As it is given in the
reducerMiddleware this middleware function must have two arguments as
dispatchMiddleware. As a return, it also takes state object, action object, and dispatch function (line 20).
Now, let’s put the pieces together. We need a component that we can send new messages by clicking a button and displaying messages that come via WebSocket. I named this component “Messager”. In this component, we also use the state values that come from the provider. We already created a hook called
After we done with this component, we need to import it into App.js
As final, we should wrap our whole application with the provider. We can use index.js for that. This is also where we add our middleware function.
In this example, only one middleware function has been created but it can be more than one. It is also possible to create a function without dispatch action. In the applications which don’t require update actions for the state by the control of middleware, we can just pass the default dispatch as a return in the