React Hot Reload 代码更改在 MobX 商店中进行

React HotReload CodeChanges made in MobX Store

我总是需要重新启动开发服务器以显示我在我的 mobx 商店 class 中所做的更改,例如将值记录到控制台中,这对开发人员来说并不友好。在更改 Store.ts 代码时,我愿意接受任何可能影响 hot-reload 行为的解决方案。这是我对 nextJs 的实现。

_app.tsx

import { StoreProvider } from 'components/configurator/StoreProvider';

function App({ Component, pageProps }: AppProps) {
    return (
        <StoreProvider {...pageProps}>
            <Component {...pageProps} />
        </StoreProvider>
    );
}

export default App;

StoreProvider.tsx

import { createContext, useContext } from 'react';
import { CartStore } from 'shared/store';

let store;
export const StoreContext = createContext<CartStore>({} as CartStore);

export function useStore() {
    const context = useContext(StoreContext);
    if (context === undefined) {
        throw new Error('useStore must be used within StoreProvider');
    }

    return context;
}

export function StoreProvider({ children, initialState: initialData }) {
    const store = initializeStore(initialData);

    return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
}

function initializeStore(initialData = null) {
    const _store = store ?? new CartStore();

    // If your page has Next.js data fetching methods that use a Mobx store, it will
    // get hydrated here, check `pages/ssg.js` and `pages/ssr.js` for more details
    if (initialData) {
        _store.hydrate(initialData);
    }

    // For SSG and SSR always create a new store
    if (typeof window === 'undefined') return _store;

    // Create the store once in the client
    if (!store) store = _store;

    return _store;
}

Store.ts

import { makeAutoObservable } from 'mobx';
import { enableStaticRendering } from 'mobx-react-lite';
import { ProductGroupData } from './APITypes';

// NextJS specific, don´t render server-side
enableStaticRendering(typeof window === 'undefined');

export interface ProductGroup extends ProductGroupData {}

export class CartStore {
    productGroups: ProductGroup[] = [];

    constructor() {
        makeAutoObservable(this);
    }

    hydrate = (data) => {
        if (!data) return;

        this.productGroups = data.productGroups;
    };

    updateProductGroups = (productGroup: ProductGroup) => {
        const packageAlreadyInStore = this.productGroups.find((x) => x.name === productGroup.name);

        if (!packageAlreadyInStore) {
            this.productGroups.push(productGroup);
        } else {
            this.productGroups = this.productGroups.filter((x) => x.name !== productGroup.name);
        }
    };
}

我自己想出来了,现在我通过 pageProps.

传递 _app.tsx 中的 StoreProvder 来补水

_app.tsx

import 'styles/global.css';

import type { AppProps } from 'next/app';

import { StoreProvider } from 'components/configurator/StoreProvider';

function App({ Component, pageProps }: AppProps) {
    return (
        <StoreProvider {...pageProps} hydrationData={pageProps.hydrationData}>
            <Component {...pageProps} />
        </StoreProvider>
    );
}

export default App;

StoreProvider.tsx

import { createContext, useContext } from 'react';
import { CartStore } from 'shared/Store';

let store;
export const StoreContext = createContext<CartStore>({} as CartStore);

export function useStore() {
    const context = useContext(StoreContext);
    if (context === undefined) {
        throw new Error('useStore must be used within StoreProvider');
    }

    return context;
}

export function StoreProvider({ children, hydrationData: hydrationData }) {
    const store = initializeStore(hydrationData);

    return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
}

function initializeStore(hydrationData = null) {
    const _store = store ?? new CartStore();

    // If your page has Next.js data fetching methods that use a Mobx store, it will
    // get hydrated here, check `pages/ssg.js` and `pages/ssr.js` for more details
    if (hydrationData) {
        _store.hydrate(hydrationData);
    }

    // For SSG and SSR always create a new store
    if (typeof window === 'undefined') return _store;

    // Create the store once in the client
    if (!store) store = _store;

    return _store;
}