About redux
Tags: react
Published: 2022-03-02 04:30:09

I've never used redux before. Today i tried redux-core with React. It did not work, why?
## First, why do we use redux?
Managing state, it means redux must have such functionalities like subscribes to changes, makes the components update when state changed, right?
Does redux-core have such things? the answer is No, it doesnt. That's why they created react-redux.
## The reducer function.
Simply take the previous state and the action, which is a normal object, but we usually structure this as a object with 2 fields: type(string) and payload(any), of course we can use any type but that is not recommended.
## How redux initiated the state?
There's 2 way to initial Redux state, arcorrding to the docs.
The first way is passing the `preloadedState` to `createStore` function. Nothing to say about this way.
The second way is by passing the reducer's default argument for `state`, something like `const reducer = (state = defaultState, action) => ...`.
Arcorrding to the docs, redux will dispatch abitrary action to get the `default-state`, that action will fall in to the `default` case we provided(if we use `switch` to determine the type).
```
createStore(combineReducers({
    test1: (state = 'YESY', action: any) => { console.log('test1', state, action); return state; },
    test2: (state = 'YESY2', action: any) => { console.log('test2' ,state, action); return state; },
  })
```
You will get the store of { test1: 'YESY', test2: 'YESY2' }
The initial state is always the default value of `state`? No, it is not, since redux dispatches some dummy actions to get the default state, it runs our reducer and treat the return-value as a default state.
Try this
```
createStore(combineReducers({
    test1: (state = 'YESY', action: any) => { console.log('test1', state, action); return 'NOT_A_DEFAULT_VAL'; },
    test2: (state = 'YESY2', action: any) => { console.log('test2' ,state, action); return state; },
  })
```
You will get the store of { test1: 'NOT_A_DEFAULT_VAL', test2: 'YESY2' }
## We dispatch a action, which reducers will be run?
Redux passes the action to all the reducer, if the reducer expects action, it will return new state, otherwise returns the previous state(maintained the referrence)(this depends on your implementation, it might return previous state or something else). So i guess if we have about 10000 reducers :D, our app will be so freaking slow.
## What applyMiddleware does?
Ive felt very confuse the first time read the docs, it said take the dispatch, return new dispatch, i cant figure out how it works fromt the docs, so i choose to read the source code :D
![applyMiddleware](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/963oxlxiiq10u3pwvqqz.png)
`applyMiddleware` creates new dispatch function, redux assign this dispatcher to `store`. The dispatch is created by calling `compose(...chain)(store.dispatch)`
`chain` is created by mapping all the middleware to the result returned by calling itself with the `context`, `context` contains the `getState, and the default dispatcher`, note that it map, not reduce, so every context passed to the middleware are the same and **middlewares passed to applyMiddleware will be called from left to right**
Continue on, the chain will be composed together, but what `compose` does? `compose` takes a list of function, then returns a functiont that take only 1 parameter, when we call the function, first the last function in compose'parameter will be called, get the value returned, call the last-1 function with that value, and so on to the first parameter. Confuse right, here is a example: `compose(fn1, fn2, fn3)(input) => fn1(fn2(fn3(input))`, **dispatcher returned by applyMiddleware will be called from right to left**. It means **whatever the chain is, the first middleware will take the original-action, the final-action will depends on what the first middleware's dispatcher returns, usually we will call the next dispatcher and get back the (modified) action, and do things with the action returned**.
Back to the `applyMiddleware`, new dispatcher is created by calling `compose` with `chain`, and pass in a default dispatcher, note that default dispacher and new dispacher is the same type, so `chain` must be a list of function that take a dispatcher and return a dispatcher, arcorrding to how `compose` works.
Finnally we can simplify the parameter of `applyMiddleware` like so:
```
({ dispatch: defaultDispatch, getState }) => lastDispatch => newDispatch
```
What is the lastDispatch of the last middleware we passed? it simply the function that returns whatever i takes. `lastDispatch = (action) => action`.
What if one middleware didnt call the lastMiddleware? The chain will stop right at that middleware, any middleware after that will not be called, and makes no effect.
The only thing a dispatcher can do is modify the `action` passed to it, but how we archieve the modified action? That's the question i asked myself, the answer is returning the modified version, so the dispacher that called it can get back the modified action. **Whatever we wanna do in our middleware's dispacher, better return an action**

![How it works](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pt84cytu33wurwksr9xn.png)