redux、mobx

居星阑
2023-12-01

状态管理

设计一个数据时需要考虑哪些问题?

生命周期:

  1. DB:随着用户的登录就存在,而且可持久化。
  2. localStorage
  3. sessionStorage
  4. project runtime:
    1. redux:生命周期,是浏览器访问,知道页面刷新或关闭。
  5. page
  6. component
这个生命周期中含有什么?

这里的deps的生命周期,和 redux 一致。

const deps = {};
function create() {
	deps.value = 'hello';
}
export default create;

redux

createStore

createStore:这个API最终返回一个store对象,所有的功能都在这个对象上。

store.subscribe:订阅state的变化。当state变化时会执行回调,可以有多个subscribe,里面的回调依次执行。

store.dispatch:发出action的方法,每次dispatch一个action,都会reducer函数,生成新的state,然后执行subscribe注册的回调。

store.getState:返回当前的state。

有什么问题

多人开发的过程中,一不小心,就会把数据清空,或者勿修改了其他组件,副作用太大。
因此,我们需要制定一个 state 的 “修改计划”, 告诉store,我的修改计划是什么。

reducer : 修改store.changeState 方法,告诉他修改state的时候,按照我们的计划执行。

精髓1

通过 reducer 来控制对数据的修改方式和预期。

精髓2

处理副作用。

  1. redux-compose:
export default compose(...funcs) {
	return funcs.reduce(
		(a, b) => (...args) =>a(b(args));
	);
}
  1. applyMiddleWare
function applyMiddleware = (...middlewares) =>{
	createStore => (reducer, preloadedState) => {
		//1.middleware即为我们上述的中间件,第一个参数是store
		const store = createStore(reducer, preloadedState);
		const middlewareAPI = {
			getState: store.getState,
			dispatch: (...args) => dispatch(...args);
		};
		//2.chain中的item为接收next的中间件函数
		const chain = middlewares.map(middleware => middleware(middlewareAPI));
		//3.store.dispatch即为上述的next函数,在代码中,以next(action)进行执行
		//4.将新的dispatch范湖出去,dispatch还是一个函数,函数的参数为
		return {
			...store, dispatch
		}
	}
}
精髓3

react-redux 的核心:

  1. redux是全局数据
  2. redux不会触发界面更新
  3. react-redux:用Context的provider和consumer把redux的store串了起来。
用法
//store/redux.js
export function createStore(reducer, initState) {
  let state = initState;
  let listeners = [];
  // 订阅函数的实现
  function subscribe(listener) {
    listeners.push(listener);
  }
  //发布通知:不让你在dispatch时修改数据,只让你告诉我在dispatch时怎么修改数据
  function dispatch(action) {
    state = reducer(state, action);
    //发布
    for (let i = 0; i < listeners.length; i++) {
      listeners[i]();
    }
  }
  dispatch({
    type: Symbol()
  });
  function getState() {
    return state;
  }
  return { subscribe, dispatch, getState };
}
export function combineReducers(reducers) {
  const keys = Object.keys(reducers);
  return function combination(state = {}, action) {
    const nextState = {};
    //遍历一遍所有的reducers,整合成一个新的state
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i];
      const reducer = reducers[key];
      const prev = state[key];
      const next = reducer(prev, action);
      nextState[key] = next;
    }
    return nextState;
  }
}

// Provider.js
import React, { Component } from 'react'
import PropTypes from 'prop-types';
export default class Provider extends Component {
  static childContextTypes = {
    store: PropTypes.object
  }
  constructor(props, context) {
    super(props, context);
    this.store = props.store;
  }
  render() {
    return this.props.children;
  }
}

// context.js
import { createContext } from "react";
export default createContext();

// connect.jsx
import PropTypes from 'prop-types';
import React, { useContext, useState,useEffect } from 'react';
import ReduxContext from './context';
export const connect = (mapStateToProps, mapDispatchToProps) => Component => {
  class Connect extends React.Component {
    componentDidMount() {
      this.context.subscribe(this.handleStoreChange.bind(this));
    }
    handleStoreChange() {
      this.forceUpdate();
    }
    render() {
      return (
        <Component {...this.props} {...mapStateToProps(this.context.store.getState())} {...mapDispatchToProps(this.context.store.dispatch)} />
      )
    }
  }
  Connect.contextTypes = {
    store: PropTypes
  }
  return Connect;
}
function Connect(props) {
  const store = useContext(ReduxContext);
  const [, setCount] = useState(true);
  const forceUpdate = () => setCount(val => !val);
  useEffect(() => store.subscribe(forceUpdate), []);
  return (
    <ReduxContext.Consumer>
      {
        store => 
          <Component {...props} {...mapStateToProps(store.getState())} {...mapDispatchToProps(store.dispatch)} />
      }
    </ReduxContext.Consumer>
  )
}

// store/index.js
import { combineReducers, createStore } from "./redux"
import { applyMiddleware } from 'redux';
import ReduxLogger from 'redux-logger';
// import { combineReducers, legacy_createStore as createStore } from "redux"
let initState = {
  counter: { count: 0 },
  info: { age: 12 }
}
function counterReducer(state, action) {
  switch (action.type) {
    case "ADD_COUNT":
      return { count: state.count+1 }
    case 'MINUS_COUNT':
      return { count: state.count-1 }
    default:
      return state;
  }
}
function infoReducer(state, action) {
  switch (action.type) {
    case 'ADD_COUNT':
      return { age: state.age+1 }
    case 'MINUNS_AGE':
      return { age: state.age-1 }
    default:
      return state;
  }
}
const reducers = combineReducers({
  counter: counterReducer,
  info: infoReducer
});
const store = createStore(reducers, initState);
export default store;


// index.js
// redux 
// import { Provider } from 'react-redux';
import Provider from './store/Provider'
// import ReduxContext from './store/context';
import store from './store/index';
ReactDom.render(
  <Provider store={store}>
    <App/>
  </Provider>,
  document.getElementById('root')
);

// App.js
// import create from './store/redux';
import Hello from './Hello';
function App() {
  return (
    <div className='App'>
      <header className='App-header'>
        hello~~
      </header>
    </div>
  )
}
export default App;

// Hello.jsx
// import { connect } from 'react-redux';
import { connect } from './store/connect';
function Hello(props) {
  return (
    <div>
      {props.counter.count}
      <button onClick={() => props.addCount()}>add</button>
    </div>
  )
}
const mapStateToProps = (state) => ({
  counter: state.counter
});
const mapDispatchToProps = (dispatch) => {
  return {
    addCount: () => dispatch({
      type: 'ADD_COUNT'
    });
  }
}
export default connect(mapStateToProps, mapDispatchToProps)(Hello);

mobx

  1. Vue react 不是很喜欢用
  2. mobx 源码中API太多了
  3. mobx 不同的版本差异比较大

mobx 本身也只是一个响应数据状态变更的一个库。

 类似资料: