手写redux

63 阅读2分钟

资源:

什么是reducer

  • reducer就是一个纯函数,接收旧的state和action,返回新的state
  • 之所以将这样的函数称之为 reducer,是因为这种函数与被传入 Array.prototype.reduce(reducer, ?initialValue) 里的回调函数属于相同的类型。保持 reducer 纯净非常重要
// 这是一个reducer函数
function countReducer(state = 0, action) {
  switch (action.type) {
    case "ADD":
      return state + 1;
    case "MINUS":
      return state - 1;
    default:
      return state;
  }

首先我们通过redux去实现一个store

import { createStore } from 'redux'

function countReducer(state = 0, action) {
  switch (action.type) {
    case "ADD":
      return state + 1;
    case "MINUS":
      return state - 1;
    default:
      return state;
  }
  
const store = createStore(countReducer)

export default store
  • 创建一个组件去调用redux内的API
import React from 'react'
import store from './../store'

class ReduxPage extends React.Component {

    componentDidMount() {
        store.subscribe(() => {
           // 更新页面显示函数
            this.forceUpdate()
        })
    }

    add = () => {
        store.dispatch({ type: 'ADD' })
    }

    render() {
        return (
            <div>
                <button onClick={this.add}>{store.getState()}</button>
            </div>
        )
    }
}

export default ReduxPage

  • 根据上面的代码我们用到了redux的createStore,那么我们现在就可试着去实现一个createStore

  • 创建一个createStore函数

  • createStore函数接收一个参数,这个参数是我们新建好的reducer函数

  • 上述组件中用到了store内的getState,dispatch,subscribe,所以我们创建的createStore也要返回这些函数

// createStore接收一个reducer
const createStore = (reducer) => {
   // 我们知道通过store内的api是去更改当前的state,所以会返回一个新的state
   let currentState
   // 存储我们的listener函数
   let currentListener = []
   // 通过getState去返回新的state
   function getState(){
       return currentState
   }
   // 在组件中 dispatch 接收一个对象参数{type: 'ADD'}, 我们称它为action
   // 通过reducer函数调用传递我们的action,返回新的state
   function dispatch(action){
      currentState = reducer(action)
      // 当每次reducer返回新的值的时候去调用一次订阅函数
      currentListener.forEach(listener => listener())
   }
   // 这是一个订阅方法,帮助我们订阅更新页面显示
   // 这个方法有可能会出现多次调用,只要dispatch就是一个listener
   function subscribe(listener){
       currentListener.push(listener)
       // 当调用完成后,卸载这个方法
       return () => {
           // 获取当前方法存在这个list中的下标
           const index = currentListener.indexOf(listener)
           // 调用完成后删除这个方法
           currentListener.splice(index,1)
       }
   }
   
   return {
      getState,
      dispatch,
      subscribe
   }
}

export { createSore }

这样我们就实现了一个简单的redux