next.js中使用mobx全局状态管理(上号七步诗)

2,637 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

next.js使用mobx

前言: 最近在完成大三的一个课程期末设计,独立完成做了一个博客社区,主要技术栈是:

前端:next.js + mobx + ts + antd;

后台管理系统:vue3.0 + pinia + ts + elementUI

后端:next.js + ts + 阿里云oss存储 + redis

开发的时候遇到了很多坑,后面会通过文章的方式总结自己在开发过程中踩到的坑以及一些小经验。

之前用react开发的时候,使用redux作为全局状态管理,感觉配置比较麻烦,所以就尝试了一下其他的react全局状态管理,下面分享一下使用mobx这个全局状态管理

只需要按照下面配置方式,就可以轻松七步实现全局状态管理了

第一步:上号,买英雄,下载依赖(安装两个依赖)

yarn add mobx mobx-react-lite

第二步:排兵布阵(我中单),建立store文件夹以及基本的store代码

image-20220513161747110.png

index.ts是把这个store暴露给外部使用store的

rootStore.ts作为所有用户定义的store状态的根节点

第三步:天赋选择(你需要用到哪些全局状态共享),实现 store/userStore.ts:

export type IUserInfo = {
  userId?: number;
  nickname?: string;
  avatar?: string;
  id?: number;
  introduce?: string;
  job?: string;
  skill?: string;
};
​
export interface IUserStore {
  userInfo: IUserInfo;
  // eslint-disable-next-line no-unused-vars
  setUserInfo: (value: IUserInfo) => void;
}
​
const userStore = (): IUserStore => {
  return {
    userInfo: {},
    setUserInfo: function (value) {
      this.userInfo = value;
    },
  };
};
​
export default userStore;

第四步:开麦,实现 store/rootStore.ts:

import userStore, { IUserStore } from './userStore';
​
export interface IStore {
  user: IUserStore;
}
​
export default function createStore(initialValue: any): () => IStore {
  return () => {
    return {
      user: { ...userStore(), ...initialValue?.user }, // 这里的...initialValue会对userStore的一些默认key进行覆盖更新
    };
  };
}

第五步: 买装备,实现 store/index.tsx

import React, { createContext, useContext, ReactElement } from 'react';
import { useLocalObservable, enableStaticRendering } from 'mobx-react-lite';
import createStore, { IStore } from './rootStore';
​
interface IProps {
  initialValue: Record<any, any>;
  children: ReactElement
}
​
enableStaticRendering(!process.browser);
​
const StoreContext = createContext({});
​
export const StoreProvider = ({ initialValue, children }: IProps) => {
  const store: IStore = useLocalObservable(createStore(initialValue));
  return (
    <StoreContext.Provider value={store}>{children}</StoreContext.Provider>
  );
};
​
export const useStore = () => {
  const store: IStore = useContext(StoreContext) as IStore;
  if (!store) {
    throw new Error('数据不存在');
  }
  return store;
};

第六步:呼叫野爹,在pages/_app.tsx中引入

import 'styles/globals.css'
import type { AppProps } from 'next/app'
import { StoreProvider } from 'store/index'function MyApp({ Component, pageProps }: AppProps) {
  return (
    <StoreProvider initialValue={{ user: {} }}>
      <Component {...pageProps} />
    </StoreProvider>
  )
}

第七步、victory!,使用它

在使用的页面中引入useStore、并且通过observer包裹组件,这样就可以监听状态的变化来更新DOM了

import { useStore } from 'store/index'
import { observer } from "mobx-react-lite"
const Login = () => {
    const store = useStore()
    // 获取user Store里面的信息
    console.log(store.user.userInfo)
    // 设置user Store里面的信息
    store.user.setUserInfo({
        userId: '1',
        nickname: '666'
    })
}

export default observer(Login)

ps:假如我们还要定义其他Store的话,比如定义一个common全局要用到的一些属性:

  • 新建一个commonStore.ts
export type ICommonInfo = {
  isShowDrawer?: boolean,
  defstyle?: boolean,
  showDrawer?: boolean
};
​
export interface ICommonStore {
  commonInfo: ICommonInfo;
  // eslint-disable-next-line no-unused-vars
  setCommonInfo: (value: ICommonInfo) => void;
}
​
const commonStore = (): ICommonStore => {
  return {
    commonInfo: {},
    setCommonInfo: function (value) {
      this.commonInfo = value;
    },
  };
};
​
export default commonStore;
  • 在rootStore.ts引入新建的这个commonStore
import userStore, { IUserStore } from './userStore';
import commonStore, { ICommonStore } from './commonStore';
​
export interface IStore {
  user: IUserStore;
  common: ICommonStore
}
​
export default function createStore(initialValue: any): () => IStore {
  return () => {
    return {
      user: { ...userStore(), ...initialValue?.user }, // 这里的...initialValue会对userStore的一些默认key进行覆盖更新
      common: { ...commonStore(), ...initialValue?.common }
    };
  };
}