Developers familiar with React are familiar with Redux, a state management container that simply helps the front end store interactive data. What I’m talking about today is how to write a Redux by hand to dispel the myth of Redux.
Be familiar with JavaScript
Understand how Redux works
The three principles
- Single data stream
- The State read-only
- Only pure functions can be used to perform modifications
The working principle of The picture shows how Redux worksAction Creators
By distribution methoddispatch
And then distributedaction
Will beReducer
The layers are taken and processed, and finally the new lines are formedStore
Data, finally byThe React Component binding
, the page changes
Statement of the Store
We need to create a Store function
function createStore(reducer){
let state;
let getState = () = > JSON.parse(JSON.stringify(state))
return {
getState,
}
}
Copy the code
The Reducer here is a callback function
const CHANGE_TITLE = "change_title"
function reducer(state={title: "Title"}, action){
switch(action.type){
The reducer is our logic to implement the reducer
case CHANGE_TITLE:
return{... state,title: action.data}
default:
break;
}
return state
}
Copy the code
This reducer is familiar to React+Redux users, so we only need to re-reducer once for each assignment to modify the diapatch method
function dispatch(action){
state = reducer(state, action)
}
Copy the code
We have the OK distribution method, the create Store function, and we still need the render method to synchronize the page update
When creating the Render method, we must understand that the page should respond when the state changes, so we have to use a subscriber pattern to do this
Create the Render method and optimize the Dispatch method
function createStore(reducer){
let state;
function dispatch(action){
state = reducer(state, action)
// Re-render the listener function after each value change
listeners.forEach(item= > item())
}
// Add publish/subscribe mode
let listeners = []
let subscribe = (fn) = > {
listeners.push(fn)
// Add the unbinding function
return () = > {
listeners= > listeners.filter(item= >item! =fn) } }// Create an object that needs to overwrite itself for the first time
dispatch({})
let getState = () = > JSON.parse(JSON.stringify(state))
return {
getState,
dispatch,
subscribe
}
}
let CHANGE_TITLE = "change_title"
let store = createStore(reducer)
function reducer(state={title: "Title"}, action){
switch(action.type){
The reducer is our logic to implement the reducer
case CHANGE_TITLE:
return{... state,title: action.data}
default:
break;
}
return state
}
// Define a function to render a page node
function render(){
document.querySelector(".title").innerHTML = store.getState().title
}
Copy the code
Here we can see that the render method seems relatively simple, but what if the render method can be more clever rendering?
They are the key. First of all,subscribe
Is a subscription function that passes each onerender
And then put each onerender
The function goes into the listener array and waits for the next timedispatch
Loop through the array when changing the valuerender
Function, so that’s how the data has changed so that it can immediately respond to the function of the page, so let’s see what the complete code looks like
Reduce dispatch action */
function createStore(reducer){
let state;
function dispatch(action){
state = reducer(state, action)
// Re-render the listener function after each value change
listeners.forEach(item= > item())
}
// Add publish/subscribe mode
let listeners = []
let subscribe = (fn) = > {
listeners.push(fn)
// Add the unbinding function
return () = > {
listeners= >listeners.filter(item >= item! =fn) } }// Create an object that needs to overwrite itself for the first time
dispatch({})
let getState = () = > JSON.parse(JSON.stringify(state))
return {
getState,
dispatch,
subscribe
}
}
let CHANGE_TITLE = "change_title"
let store = createStore(reducer)
function reducer(state={title: "Title"}, action){
switch(action.type){
The reducer is our logic to implement the reducer
case CHANGE_TITLE:
return{... state,title: action.data}
default:
break;
}
return state
}
// Define a function to render a page node
function render(){
document.querySelector(".title").innerHTML = store.getState().title
}
// The first time the page loads the render method
render()
// With the listener we just need to
let unsubscribe = store.subscribe(render)
// The render method for each update
setInterval(() = > {
store.dispatch({
type: CHANGE_TITLE,
data: "I'm the title that I changed again."+ Math.random() * 100
})
// Cancel the useless listener function immediately after rendering
unsubscribe()
}, 2000)
// This is a simple redux implementation
Copy the code
You can put it in a page to run to see the effect, this article based on node V14 environment, will not do the effect demonstration 😜😜😜