阅读redux源码之createStore简易版

167 阅读1分钟

前言

一直想读一下redux的源码,这次终于安静下来好好读一下了。直接实现了一个自定义的createStore,感觉还不错,直接上代码。

结构

  • currentState 缓存当前的state
  • currentReducer 缓存当前的reducer
  • currentListeners 注册监听的函数集合
let currentState = preloadState;
let currentReducer = reducer;
const currentListeners = [];
  • dispatch 更改全局的state并触发监听的函数
function dispatch(action) {
    currentState = currentReducer(currentState, action);
    for (let listen of currentListeners) {
      listen();
    }
  }
  • subscribe 注册监听的函数
  • unSubscribe 卸载当前注册的监听函数
 function subscribe(listen) {
    currentListeners.push(listen);
    return function unSubscribe() {
      const index = currentListeners.indexOf(listen);
      currentListeners.splice(index, 1);
    };
  }
  • replaceReducer 替换掉当前的reducer
function replaceReducer(nextReducer) {
    currentReducer = nextReducer;
    dispatch({ type: 'replaceReducer' });
  }

createStore实现

export function crateStore(reducer, preloadState) {
  let currentState = preloadState;
  let currentReducer = reducer;
  const currentListeners = [];
  function getState() {
    return currentState;
  }
  function dispatch(action) {
    currentState = currentReducer(currentState, action);
    for (let listen of currentListeners) {
      listen();
    }
  }
  function subscribe(listen) {
    currentListeners.push(listen);
    return function unSubscribe() {
      const index = currentListeners.indexOf(listen);
      currentListeners.splice(index, 1);
    };
  }
  function replaceReducer(nextReducer) {
    currentReducer = nextReducer;
    dispatch({ type: 'replaceReducer' });
  }
  return { getState, subscribe, dispatch, replaceReducer };
}

使用

import { crateStore } from './custom/crateStore';
const reducer = (state, action) => {
  switch (action.type) {
    case 'add':
      return { ...state, count: ++state.count };
    case 'sub':
      return { ...state, count: --state.count };
    default:
      return state;
  }
};

const doubleCountReducer = (state, action) => {
  switch (action.type) {
    case 'add':
      return { ...state, count: state.count * 2 };
    case 'sub':
      return { ...state, count: state.count * 2 };
    default:
      return state;
  }
};
const store = crateStore(reducer, { count: 0 });
const unCountSubscript = store.subscribe(() => {
  const count = store.getState().count;
  console.log(count, '监听哈哈count');
});

function App() {
  return (
    <div className="App">
      <button
        onClick={() => {
          unCountSubscript();
        }}
      >
        停止监听
      </button>
      <button
        onClick={() => {
          store.replaceReducer(doubleCountReducer);
        }}
      >
        注册双倍reducer
      </button>
      <button
        onClick={() => {
          store.dispatch({ type: 'add' });
          const count = store.getState().count;
          console.log(count, 'click');
        }}
      >
        加数
      </button>
    </div>
  );
}

export default App;

效果

image.png