• 状态管理使用样例


    什么是状态管理

    在react中,我们可以用过props完成一些特定场景下的状态共享,比如父子组件。但是当遇到一些其他场景时,状态共享显得特别繁琐,比如常见的跨级组件,同级组件等。虽然react提供了context API 来试图解决这方面的问题,但是还是不够优雅。现在市面上有很多优秀的状态管理库,我们一起分析看看那个更适合我们。

    Redux

    特点:

      • 三大原则:单向数据流,state只读,只能通过reduce修改,reducer必须是一个纯函数。
      • 由store,reducer,action三部分组成。store用于存放数据,reducer是触发action之后调用的更新方法更新store,action用于调用reducer。
      • redux是js的状态管理库,在react更好的使用需要搭配react-redux。
      • 不支持异步处理。需要使用三方异步中间件 。(redux-thunk,redux-saga)
      • 有一定的上手成本,需要按照规范定义模版结构,也因此是大型项目状态管理的首选方案。
    1. // main.js
    2. import store from './store';
    3. import { Provider } from 'react-redux';
    4. ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
    5. <Provider store={store}>
    6. <StrictMode>
    7. <BrowserRouter>
    8. <Layout>
    9. <Routes />
    10. Layout>
    11. BrowserRouter>
    12. StrictMode>
    13. Provider>
    14. );
    15. // store.js
    16. import { applyMiddleware, legacy_createStore as createStore, compose } from 'redux';
    17. import reducer from './reducer';
    18. import thunk from 'redux-thunk';
    19. const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
    20. const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)));
    21. export default store;
    22. // reducer.js
    23. import { combineReducers } from "redux";
    24. import { reducer as IndexReducer } from '@/pages/index/store';
    25. export default combineReducers({
    26. Index: IndexReducer,
    27. })

    Mobx

    特点:

      • 响应式数据流,监听数据变化暴漏给所有依赖的观察者组件。
      • 上手相对于redux简单,自由化相对较高。(适合中小型项目,不适合多人开发)
      • 支持异步。
    1. // store.js
    2. import { action, observable, makeObservable } from 'mobx';
    3. class Store {
    4. constructor() {
    5. makeObservable(this, {
    6. count: observable,
    7. list: observable,
    8. setCount: action,
    9. setList: action
    10. })
    11. }
    12. count = 1;
    13. list = {};
    14. setCount() { this.count++ };
    15. setList(data) { this.list = data };
    16. }
    17. export const store = new Store();
    18. // demo.js
    19. import { useObserver, useLocalStore } from 'mobx-react';
    20. import { store } from './store';
    21. const Demo1 = () => {
    22. const localStore = useLocalStore(() => store);
    23. const addCount = () => {
    24. localStore.setCount()
    25. }
    26. const changeList = () => {
    27. localStore.setList({ name: 'kobe' })
    28. }
    29. return useObserver(() =>
    30. <div className='demo2'>
    31. <button onClick={addCount}>改变countbutton>
    32. <button onClick={changeList}>改变Listbutton>
    33. <p>count:{localStore.count}p>
    34. <p>list:{localStore.list.name}p>
    35. div>
    36. )
    37. }
    38. export default Demo1;

    Recoil

    特点:

      • 与redux相似,在根组件用过RecoilRoot包裹,通过context传递上下文。
      • 使用atom(无依赖),selector(有依赖)创建数据。
      • 上手简单,没有那么多条条框框,直接简单粗暴的定义,修改即可完成使用。
    1. import { atom, selector } from 'recoil';
    2. export const countState = atom({
    3. key: 'countState',
    4. default: 0
    5. })
    6. export const dataListState = atom({
    7. key: 'dataListState',
    8. default: {}
    9. })
    10. export const dataState = selector({
    11. key: 'dataState',
    12. get: ({ get }) => {
    13. const count = get(countState);
    14. const dataList = get(dataListState);
    15. return {
    16. count,
    17. dataList
    18. }
    19. }
    20. })
    21. // 消费
    22. import { useRecoilState, useSetRecoilState,useRecoilValue,useResetRecoilState } from 'recoil';
    23. const [count, setCount] = useRecoilState(countState); // 与useState类似,提供读写方法
    24. const setDataList = useSetRecoilState(dataListState); // 仅修改
    25. const { count, dataList } = useRecoilValue(dataState);// 只读
    26. const reset = useResetRecoilState(dataState);// 重置

    Zustand

    特点:

      • 通过create创建数据,在回调方法中暴漏set,get等api用于读写当前数据。
      • 上手简单,写法上与Recoil类似。
      • 支持异步。
    1. // store.js
    2. import create from "zustand";
    3. const useStore = create((set) => ({
    4. votes: 0,
    5. list: {},
    6. addVotes: () => set(state => ({ votes: state.votes + 1 })),
    7. subVotes: () => set(state => ({ votes: state.votes - 1 })),
    8. getList: async () => {
    9. const data = await mockData();
    10. set({ list: data })
    11. }
    12. }))
    13. export { useStore }
    14. // demo.js
    15. import { useStore } from './store';
    16. import shallow from 'zustand/shallow';
    17. const Demo1 = () => {
    18. const { addVotes, subVotes, getList } = useStore(state => ({ addVotes: state.addVotes, subVotes: state.subVotes, getList: state.getList }), shallow);
    19. // const subVotes = useStore(state => state.subVotes);
    20. return <div>
    21. <button onClick={addVotes}>addVotes++button>
    22. <button onClick={subVotes}>subVotes--button>
    23. <button onClick={getList}>getDatabutton>
    24. div>
    25. }
    26. export default Demo1;

    Dva

    特点:

      • react状态管理的轻量框架,dva = react-router + redux + redux-sage + fetch。
      • api简单,上手难度低。
      • 支持异步,与umi搭配之后,复杂度更低。
    1. // app.js
    2. import dva from 'dva';
    3. // Initialize
    4. const app = dva();
    5. // Model
    6. app.model(require('./models/example').default);
    7. // Router
    8. app.router(require('./router').default);
    9. // Start
    10. app.start('#root');
    11. // 定义modal
    12. import { mockData } from '../utils/mock'
    13. export default {
    14. namespace: 'example',
    15. state: {
    16. list: {}
    17. },
    18. reducers: {
    19. getlist(state, { data }) {
    20. console.log('state====', state);
    21. return { ...state, list: data };
    22. },
    23. },
    24. effects: {
    25. *getlistAsync({ payload }, { call, put }) {
    26. const data = yield call(mockData);
    27. yield put({ type: 'getlist', data });
    28. },
    29. },
    30. };
    31. // 消费
    32. import { connect } from 'dva';
    33. import Name from './name'
    34. function IndexPage(props) {
    35. const { dispatch } = props
    36. const getlist = () => {
    37. dispatch({
    38. type: "example/getlistAsync",
    39. })
    40. };
    41. return (
    42. <div className={styles.normal}>
    43. <button onClick={getlist}>获取列表数据button>
    44. <Name />
    45. div>
    46. );
    47. }
    48. const mapStateToProps = (state) => {
    49. return {
    50. example: state.example,
    51. };
    52. };
    53. export default connect(mapStateToProps)(IndexPage);
    54. // name 子组件
    55. import { connect } from 'dva'
    56. const Name = ({ list }) => {
    57. return <p>name:{list.name}p>
    58. };
    59. const mapStateToProps = (state) => {
    60. return {
    61. list: state.example.list
    62. };
    63. };
    64. export default connect(mapStateToProps)(Name);

    引用

    Recoil

    Mobx

    Redux

    Zustand

    Dva

  • 相关阅读:
    torch_vision(一):数据增强和转换模块torchvision.transforms
    软件设计师考试学习1
    [ flex ] -- 父盒子ul为flex布局时宽度不够,子盒子li无法被撑开的问题(li的宽度被压缩)
    Linux脚本练习之script083-nginx日志分析之查询某个IP的详细访问情况
    简单记录关于Velocity的一些想法
    JavaScript实现复制粘贴功能的原理与应用
    VPP以太网接口模式
    [spring-04]Bean后处理器
    【编程题】【Scratch四级】2021.09 计算并联电阻的值
    SAP PS 第9节 合并采购申请、组合WBS之详解
  • 原文地址:https://blog.csdn.net/zlzbt/article/details/128111994