Reducer
What is reducer, a pure function that accepts old states and actions and returns new states
(preState,action)=>newState
Copy the code
Reducer is called because it belongs to the same type as the callback function in array.prototype. reduce(Reducer, initialValue).
It is important to keep the reducer clean and never do anything from the Reducer:
- Modify incoming parameters
- Perform operations that have side effects, such as API requests and route jumps
- Call impure functions such as date.now () or math.random
compose
If a value passes through multiple functions to become another value, you can combine all the intermediate steps into a single function, which is called composition of the function.
The benefits of composition are obvious: it makes code simpler and more readable, and it makes it easier to combine other commonly used functions in different combinations, making code more expressive
/** * combinatorial functions */
function f1(arg) {
console.log("f1", arg);
return arg;
}
function f2(arg) {
console.log("f2", arg);
return arg;
}
function f3(arg) {
console.log("f3", arg);
return arg;
}
function compose(. funcs) {
if (funcs.length === 0) {
return arg= > arg;
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce((a, b) = > (. args) = >a(b(... args))); } compose(f1,f2)("omg");
// console.log(compose(f1, f2, f3)("omg"));
Copy the code
Redux
Redux is a state container for Javascript applications. It is written in pure JS to ensure consistent behavior and easy to test
Examples of Redux applications
1. You need a store to store data
2. The Reducer in the store initialized state and defined state modification rules
Commit changes to the data by dispatching an action
Actions are submitted to the Reducer function and new states are returned based on the action type
checkpoint
1. CreateStore creates a store
2. Reducer initialized and modified the state function
3. GetState Gets the status value
4. Dispatch commits the update
5. Subscribe
Handwriting redux related apis
Store (Application container)
// index.js
// import { createStore, applyMiddleware, combineReducers } from "redux";
import { createStore, applyMiddleware, combineReducers } from "./kredux";
// import thunk from "redux-thunk"; // handle asynchrony
// import logger from "redux-logger"; // Prints logs
function countReducer(state = 0, { type, payload }) {
switch (type) {
case "ADD":
return state + payload;
case "MINUS":
return state - payload;
default:
returnstate; }}const store = createStore(
// countReducer,
combineReducers({ count: countReducer }), // Multiple reducer processes
applyMiddleware(thunk, logger)
);
export default store;
Copy the code
Export the ES6 module
// index.js
import createStore from "./createStore";
import applyMiddleware from "./applyMiddleware";
import combineReducers from "./combineReducers";
export { createStore, applyMiddleware, combineReducers };
Copy the code
CreateStore (Create container)
export default function createStore(reducer, enhancer) {
// Perform the following if middleware exists
if (enhancer) {
return enhancer(createStore)(reducer);
}
// If the initial state is undefined, it can be passed in by the user
let currentState;
let currentListeners = [];
// get
function getState() {
return currentState;
}
// set
function dispatch(action) {
currentState = reducer(currentState, action);
// State changes to execute subscribed functions
currentListeners.forEach(listener= > listener());
}
// Subscribe and unsubscribe should come in pairs
function subscribe(listener) {
currentListeners.push(listener);
// Return a function to remove listeners from currentListeners
return () = > {
const index = currentListeners.indexOf(listener);
currentListeners.splice(index, 1);
};
}
// Execute dispatch to set the initial value
dispatch({ type: "REDUXXXXXXXXXXXX" });
return {
getState,
dispatch,
subscribe
};
}
Copy the code
applyMiddleware
import compose from "./compose";
export default function applyMiddleware(. middlewares) {
return createStore= > reducer= > {
/ / store
const store = createStore(reducer);
// Regular dispatch
let dispatch = store.dispatch;
// Enhanced dispatch
let midAPI = {
getState: store.getState,
// Each middleware has its own scope
dispatch: (action, ... args) = >dispatch(action, ... args) };// Execute middleware array
const middlewareChain = middlewares.map(middleware= > middleware(midAPI));
// Execute sequentially with the compose composition function to get the enhanced dispatchdispatch = compose(... middlewareChain)(store.dispatch);return { ...store, dispatch };
};
}
Copy the code
CombineReducers (Combine multiple reducers into a single reducer)
export default function combineReducers(reducers) {
return function combination(state = {}, action) {
let nextState = {};
let hasChanged = false;
for (const key in reducers) {
constreducer = reducers[key]; nextState[key] = reducer(state[key], action); hasChanged = hasChanged || nextState[key] ! == state[key]; }// Change the reducer dynamically
hasChanged =
hasChanged || Object.keys(nextState).length ! = =Object.keys(state).length;
return hasChanged ? nextState : state;
};
}
Copy the code
Story – thunk middleware
The middleware handles cases where the dispatches of the scenario are functions, such as asynchronous logic
// Write a thunk by hand to handle asynchronous thunk
export default function thunk({ getState, dispatch }) {
return next= > action= > {
// Next is compose() in applyMiddlerware
// Action is equivalent to dispatch
if (typeof action === "function") {
return action(dispatch, getState);
}
return next(action);
};
}
Copy the code
Story – logger middleware
Print log
// Write a logger by hand and print the log
export default function logger({ getState, dispatch }) {
return next= > action= > {
console.log("-- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
console.log(action.type + "Executed.");
const preState = getState();
console.log("pre state", preState);
const returnValue = next(action);
const nextState = getState();
console.log("next state", nextState);
console.log("-- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
return returnValue;
};
}
Copy the code
The last complete code address is github