3

我试图在一个组件中访问 2 个不同的商店,但担心我的应用程序的架构可能需要更改,因为easy-peasy可能没有此功能。

我有一个GlobalStore

import { createStore } from 'easy-peasy';

const globalModel = {
  menuOpen: false,
  toggleMenu: action((state, payload) => {
    state.menuOpen = payload;
  }),
};

const GlobalStore = createStore(globalModel);
export default GlobalStore;

仅对于此示例,我将使用商店中使用的单个状态和操作来定义导航菜单是否打开。

App.jsGlobalStore 出现在我的文件中我的应用程序的顶层。

import React from 'react';
import { StoreProvider } from 'easy-peasy';
import GlobalStore from './store/GlobalStore';

const App = () => {
  return (
    <StoreProvider store={GlobalStore}>
    </StoreProvider>
  );
};

export default App;

现在,在树的更下方,我有另一个商店SearchStore,它指示组件中哪个视图处于活动状态。

import { createStore } from 'easy-peasy';

import { action } from 'easy-peasy';

const searchModel = {
  view: 'filter',
  setView: action((state, payload) => {
    state.view = payload;
  }),
};

const SearchStore = createStore(searchModel);
export default SearchStore;

我现在遇到的问题是,在一个组件中,我需要能够访问两个商店以使用中的setView操作更新视图并从其中SearchStore获取值,但不能同时访问两者。menuOpenGlobalStore

我在一个组件中的示例是我有一个样式化的组件,单击该组件时会调用该操作setView,但其位置也由是否menuOpen定义true。但显然,如果我尝试获取menuOpen它的状态将是未定义的,因为它不存在于 SearchStore

const Close = styled.span`  
  $(({ menuOpen }) => menuOpen ? `
   // styles go here
  ` : `` }
`;

const setView = useStoreActions((action) => action.setView);
const menuOpen = useStoreState((state) => state.menuOpen);

<Close menuOpen={menuOpen} onClick={() => setView('list')}>

这可能吗?任何帮助将非常感激。

4

1 回答 1

3

备选方案一:扩展全球商店

要访问这两个商店(通过useStoreState/Actionsfrom StoreProvider),您可以将两个“子”商店嵌套到GlobalStore

// SearchModel.js
import { action } from 'easy-peasy';

const searchModel = {
  view: 'filter',
  setView: action((state, payload) => {
    state.view = payload;
  }),
};

export default searchModel;
// MenuModel.js
import { action } from 'easy-peasy';

const menuModel = {
  isOpen: false,
  toggle: action((state, payload) => {
    state.isOpen = !state.isOpen;
  }),
};

export default menuModel;
// GlobalStore.js
import { createStore } from 'easy-peasy';

import menu from './MenuhModel';
import search from './SearchModel';

const globalModel = {
  menu,
  search,
};

const GlobalStore = createStore(globalModel);
export default GlobalStore;

这样,您可以使用钩子在方便时访问这两个商店:

const searchState = useStoreState((state) => state.search);
const menuState = useStoreState((state) => state.menu);

const searchActions = useStoreActions((action) => action.search);
const menuActions = useStoreActions((action) => action.menu);

备选方案 2:useLocalStore()

如果您不想扩展全局存储,可以使用以下命令创建本地存储useLocalStore()

function Menu() {
  const [state, actions] = useLocalStore(() => ({
    isOpen: false,
    toggle: action((state, payload) => {
      state.isOpen = !state.isOpen;
    }),
  }));

  return (
    <div>
      {state.isOpen && <MenuItems />}
      <button onClick={() => actions.toggle()}>Open menu</button>
    </div>
  );
}

然而,这种方法的缺点是状态不是全局的,只能在组件级别使用。

但是,您可以通过创建自己的提供程序来解决此问题 - 但话又说回来,替代方案 1 可能是阻力最小的路径。

于 2021-02-26T17:26:46.780 回答