What Even Is A Dispatch Function?
Tags: javascript, react, redux, usereducer
Published: 2020-02-15 16:02:23

Learning redux? Or `useReducer`? Then chances are you've been frustrated by the black magic that is the `dispatch` function 🧙‍♂️! Well, luckily you have found this post. I will help you understand what happens under-the-hood and remove the mystery behind `dispatch`.

![https://images.unsplash.com/photo-1551269901-5c5e14c25df7?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb](https://images.unsplash.com/photo-1551269901-5c5e14c25df7?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb)

## What makes dispatch so hard?

There are a couple of reasons that learning Redux or the reducer hooks can be confusing. 

First - both flows rely on a programming paradigm called "functional programming". Thinking in this way requires you to switch your mental model of how to manage data in your application. *For more on functional programming, read the first half of this article - [Functional Programming in JavaScript: How and Why](https://blog.bitsrc.io/functional-programming-in-javascript-how-and-why-94e7a97343b)*. The basic idea here that makes these patterns hard is that data is flowing from function to function, and often changes shape a little (or even a lot 😬) before your state is updated and the component re-renders.

Second - both flows "abstract" some of the logic into different functions. Think about it. If you're using Redux, you call an action creator function and **POOF**... a reducer is called and `state` and an `action object` are passed in. Like, what the heck?!? 😡 The reducer hook flow has one less layer of abstraction, but there is still some there that adds to the confusion. 

## Rebuilding dispatch

I think looking at how the dispatch function is built really helps remove the mystery behind reducers. So let's build a simple implementation of dispatch to see the logic that is abstracted out of our view. We start with the function definition.

```javascript
function dispatch() {
    	
}
```

Wooooo 🎉! We're doing great so far 😁. Next step, we will add `action` as a parameter for the function.

```javascript
function dispatch(action) {
    	
}
```

So, with this, we know that when the dispatch function is called, it will be passed an action object as an argument. If you're using `useReducer` or `useDispatch`, you already know this. Upon some kind of event occurring in the UI, *you*, not the Redux library, call the dispatch function like this: `dispatch({ type: 'ACTION_TYPE' })`. If you're using Redux and the `connect` function, even that part is abstracted away from your view and it’s the Redux library that calls the dispatch function. We’ll talk more on that towards the end. Let's continue though.

Now we need to do a couple of checks. We need to make sure that the action object that is passed in is an object, and that it has a `type` property. If either of those is not true, we will throw an error. When a reducer function is written, it assumes that those are both true.

```javascript
function dispatch(action) {
  // check that the action argument is an object
  if (typeof action !== 'object' || obj === null) {
    throw new Error('actions must be plain object.');
  }
    
  // check that the action object has a 'type' property
  if (typeof action.type === 'undefined') {
    throw new Error('Actions may not have an undefined "type" property.'
  }
}
```

Good. Now we can build our reducers with confidence knowing that any action that is dispatched will be an object and will have a "type" property.

Now the exciting part! The next thing we will do is call the reducer *from within the dispatch function*. This is the abstraction part that hides from our view of what is happening behind-the-scenes. There are a couple of points that we need to cover before we can write this though. 

The dispatch function is in the same scope as the current state of the app. So that means that inside the dispatch function, we have access to an object called `currentState` that *is* the current state in our app.

In that same scope is the reducer function that we have written and passed into `createStore` or `useReducer`. So the dispatch function also has access to `reducer` - our reducer function (no matter what we called it) that we passed in. That means that the dispatch function can invoke the reducer function.

Here’s a very simplified version of what that looks like:

```JavaScript
const createStore = () => { 
  // 😮 yep, it’s createStore! But that’s for another article… 

  // state will be initialized then stored here
  const currentState = {};

  // your reducer, or combined reducers, will be accessible here
  const reducer = null;

  // dispatch function in the same scope will have access to the most current state and your reducer(s)
  const dispatch = (action) => {
    // … all the codes
  }
```

🤯 I know, I know… really cool to see what it looks like under-the-hood, right? Functions and objects. Welcome to functional programming in JavaScript! Once you see it written out like this, it starts to come together! But there is still just a little more to explore.

Let's think about everything that we've learned so far and combine that new knowledge with what we know about reducers. 
  - `dispatch` has access to `currentState` and `reducer`.
  - When `dispatch` is called, it receives an action object as an argument. 
  - A reducer function, when invoked, is passed two arguments - `state` (meaning the current state) and `action`. 
See where I'm going with this? 

Inside `dispatch` we will now call `reducer` and pass in `currentState` and the `action` object.

```javascript
function dispatch(action) {
  // check that the action argument is an object
  if (typeof action !== 'object' || obj === null) {
    throw new Error('actions must be plain object.');
  }
    
  // check that the action object has a 'type' property
  if (typeof action.type === 'undefined') {
    throw new Error('Actions may not have an undefined "type" property.');
  }
    
  // call the reducer and pass in currentState and action
  // reducer and currentState are within scope, action is the parameter passed into the function
  reducer(currentState, action);
}
```

Look at that closely... when an action is dispatched, or in other words, when we invoke `dispatch` and pass in an action object, the `dispatch` function calls our reducer and passes in the current state and the action object! 🤩 It's all starting to make sense!

Well, there's one last part to this - updating the state. Think about how you write a reducer function. What does it return? It returns a new state object, right? You've followed immutable principles to return a *copy* of the old state, updated with new data based on whichever action you had dispatched. So when the `dispatch` function does this - `reducer(currentState, action);` - that function call is going to return a brand new state object. Our dispatch function here needs to update currentState with the new state object that is returned by calling the reducer. 

```javascript
function dispatch(action) {
  // check that the action argument is an object
  if (typeof action !== 'object' || obj === null) {
    throw new Error('actions must be plain object.');
  }
    
  // check that the action object has a 'type' property
  if (typeof action.type === 'undefined') {
    throw new Error('Actions may not have an undefined "type" property.');
  }
    
  // call the reducer and pass in currentState and action
  // capture the new state object in currentState, thus updating the state
  currentState = reducer(currentState, action);
}
```

And voila! We have built a simple implementation of the `dispatch` function. Now, of course, there is more to this in the actual implementations. In Redux, `dispatch` needs to tell the app that the state has been updated. This happens through listeners and subscriptions. In the `useReducer` hook, React recognizes that the state was updated and re-renders the component. The updated state is then returned to the component from where the `useReducer` hook was called.

Regardless of the extra implementations, building out the `dispatch` function here will really help us understand what is happening under-the-hood when we call `dispatch` from our components.

## Redux and action creators

If you're using Redux and `connect`, there is one more layer of abstraction to explore. With the `connect` function, you pass action creators into an object in the `connect` function. The action creators are then passed to the component via props. In your component, when you call the action creator, it will call dispatch for you. That's the added layer of abstraction. Let's look at what `connect` does under-the-hood (again in a simplified version). 

```javascript
// inside the connect function implementation
dispatch(actionCreator());
```

So, `connect` wraps the `dispatch` function *around* the action creator call. When the action creator is invoked, it returns an action. So the above evaluates down to:

```javascript
dispatch({ type: 'ACTION_TYPE' });
```

which we now understand will call the reducer! Wooo! 🚀

## Conclusion

Hopefully, this helps remove the black magic of reducers and dispatch! If you think through the logic flow, you will realize that this is all about functions calling functions and passing data around. And now that the black magic of Redux has been removed a bit, you can get back to the fun part of building web apps with React and Redux ⚛️!