reactjs 如何在单独的组件中使用相同的Redux存储,其中没有公共根组件

guz6ccqo  于 2023-03-29  发布在  React
关注(0)|答案(1)|浏览(117)

我正在尝试设置一个可以从多个组件访问的redux商店。我是新手,但我知道通常会用提供程序 Package 根应用组件,以使相同的商店上下文在任何地方都可用。
然而,我在一个遗留应用中工作,我们在这里和那里添加React组件,没有站点范围内的公共根应用组件,只有彼此一无所知的独立组件树。我认为redux商店将是一个很好的解决方案。但是现在我意识到,在幕后进行了一些上下文处理,我不确定如何将每个提供程序与相同的上下文连接起来。我找到了一些关于提供上下文的基本信息,但我不确定这是否解决了我的问题,它正在进入杂草,特别是使用Typescript。
具体来说,我在标题中有一个迷你购物车和几个想要与该组件交互的页面。
MiniCart.tsx:

import store from '../../common/stores/store';
...
<Provider store={store}>
    <MiniCart />
</Provider>

PageThatNeedsToAddToMiniCart.tsx:

import store from '../../common/stores/store';
...
<Provider store={store}>
    <PageThatNeedsToAddToMiniCart />
</Provider>

---编辑1 ---
hooks.ts:

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'

type DispatchFunc = () => AppDispatch
const useAppDispatch: DispatchFunc = useDispatch
const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

export { useAppDispatch, useAppSelector }

miniCartSlice.tsx:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import type { RootState } from './store';

interface MiniCart {
    SubTotal: number;
}

interface MiniCartState {
    SubTotal: number;
}

const initialState: UserCart = {
    SubTotal: 0,
}

const miniCartSlice = createSlice({
    name: 'miniCart',
    initialState: initialState,
    reducers: {
        productAdded: (state, action: PayloadAction<UserCart>) => {
            return state = action.payload;
        }
    }
});

const selectSubTotal = (state: RootState) => state.miniCart.SubTotal;

export const { productAdded } = miniCartSlice.actions;
export { selectSubTotal };
export default miniCartSlice.reducer;

store.tsx:

import { configureStore } from '@reduxjs/toolkit';
import miniCartReducer from './miniCartSlice';

const store = configureStore({
    reducer: {
        miniCart: miniCartReducer
    }
})

type RootState = ReturnType<typeof store.getState>;
type AppDispatch = typeof store.dispatch;

export type { RootState, AppDispatch }
export default store;

PageThatNeedsToAddToMiniCart.tsx:

const dispatch = useAppDispatch();
...

dispatch(
    productAdded(result.UpdatedCart)
);

MiniCart.tsx:

//This value is not updated when the other component dispatches "productAdded". I expected it to trigger a rerender.
const subTotal = useAppSelector(selectSubTotal); 
...
return (
    <div> 
        <p>{`Subtotal: ${subTotal} `}</p>
    </div>
);

也许我误解了我在调试中所看到的,但这两个组件似乎访问了不同的存储区。
---编辑2 ---
事实证明,虽然我只配置了一次商店,但单独捆绑应用程序会导致单独的商店。为了简单起见,我最终选择了Jacob的答案,但可能最终会选择他更强大的建议redux-micro-frontend

xqk2d5yq

xqk2d5yq1#

如果您创建3个单独的捆绑包(应用程序A,应用程序B和商店),您可以通过事件共享商店。

应用A

// Wait to start the application until the store is created.
window.addEventListener('createStore', function(event) {
    const root = createRoot(document.getElementById('root')!);

    // pull store from the event details
    const store = event.detail;

    root.render(
        <StrictMode>
            <Provider store={store}>
                <AppA />
            </Provider>
        </StrictMode>
    )
});

应用B

// Wait to start the application until the store is created.
window.addEventListener('createStore', function(event) {
    const root = createRoot(document.getElementById('root')!);

    // pull store from the event details
    const store = event.detail;

    root.render(
        <StrictMode>
            <Provider store={store}>
                <AppB />
            </Provider>
        </StrictMode>
    )
});

储存

// Wait for page to load (might be needed so that when the react 
// applications respond to the custom event the DOM elements that
// they target are definitely created).
document.addEventListener('DOMContentLoaded', function(event) {
    const reducer = /* CONFIGURE ROOT REDUCER HERE */;
    const initialState = /* CONFIGURE INITIAL STATE HERE */;
    const middleware = /* CONFIGURE INITIAL MIDDLEWARE HERE */;
    
    // Create redux store.
    const store = createStore(reducer, initialState, middleware)
    
    // Create custom event with reference to store attached.
    const createStoreEvent = new CustomEvent('createStore', { detail: store });
    
    // dispatch createStore event
    window.dispatchEvent(createStoreEvent);
});

虽然这与在窗口上单击商店非常相似,但获取商店引用稍微困难一些(不能在控制台中输入window.并查看弹出的内容)。

相关问题