This is a simple Redux implementation from scratch. It is based on the Redux Fundamentals tutorial.
npm install
npm run dev
-
Redux is a store management library
-
In
App.tsx
, we need to have a persistent reference to the store object. Otherwise, the store will be recreated on every state change. -
compose
is used to chain up multiple functions together for many middleware functions (sideEffects).
- Problem # 1: store is recreated on every state change
useRef
is used to store the store objectuseContext
fromStoreProvider
2.1 Create a Provider architecture to store the redux store object 2.2useContext
to access the store object inApp.tsx
2.3 or create custom hooks, i.e.useStore
// ❌❌❌ this is not working as store is rerendering on every state change
const store = Redux.createStore(reducer);
// this is working as store is not rerendering on every state change
// ✅✅✅ 1. useRef is used to store the store object
const store = useRef(Redux.createStore(reducer)).current;
// 💯💯💯 2. useContext from StoreProvider
const store = useContext(StoreContext);
-
Problem # 2: notify the component when the store is updated
-
store.subscribe(listener)
is used to subscribe listeners to the store. -
When the store is updated (dispatched an action), the listeners array will be called iteratively.
-
e.g.
setCount(store.getState().count);
to update the state in the component. -
store.subscribe(listener)
returns a function to unsubscribe the listener. -
unsubscribe the listener in
useEffect
to avoid memory leaks.
-
Problem # 3: perform side effects
-
Middleware makes our code intercepting and handling actions before they reach the reducer
-
Use cases:
- Logging
- Crash reporting
- Performing asynchronous tasks
- some side effects
-
Simply return a custom dispatch/getState function, performing a single side effect task, and then call the original dispatch function.
dispatch: middleware({ getState: store.getState, dispatch: store.dispatch });
-
We have one more layer to control the dispatch function, by chaining the middleware functions together, and then call the original dispatch function.
-
middlewareAPI
is used to pass the storegetState
anddispatch
functions to the middleware functions. -
We then chain up all middleware functions, call
compose
to return a single function, and then call the original dispatch function in 1 line of code.Make good use of funcition composition.
Example
function foo(x) {
return x + 1;
}
function bar(y) {
return y * 2;
}
const result = compose(
foo,
bar,
)(1);