nx react redux store - 循环依赖
nx react redux store - circular dependcies
如何使用 react 和 redux store 解决 nx 工作空间中的循环依赖问题?
例如,如果我有一个包含所有商店配置的库,则有一个文件 createRootReducer - 它结合了我的减速器:
import {
someSliceReducer,
SOME_SLICE_FEATURE_KEY,
} from '@app/feature';
export const createRootReducer = (history: History) =>
combineReducers({
router: connectRouter(history),
form: formReducer,
[SOME_SLICE_FEATURE_KEY]: someSliceReducer,
});
商店库中的应用程序状态为:
import { createRootReducer } from './createRootReducer';
export type ApplicationState = ReturnType<ReturnType<typeof createRootReducer>>;
问题来自于在 someSliceReducer 所在的库中导入应用程序状态:
import {ApplicationState} from '@app/store'
const entities= useSelector(
(state: ApplicationState) => state.dischargeFolder.loadingStatus
);
现在我们有一个 循环依赖关系 并且 nx 警告我们:
Circular dependency between "feature" and "store" detected: feature -> store -> feature eslint@nrwl/nx/enforce-module-boundaries
如何避免这种情况?我需要在 root-reducer 中导入 reducer,但我还需要将 ApplicationState 导入到功能中。
我试图将 root-reducer 提取到自己的库中 - 但这并没有解决问题 nx 抱怨超过 3 个库的循环依赖。
我还尝试使用“reducerRegistry”,它接受一个 reducer 并在内部注册它 - 不幸的是,使用这种方法我丢失了已注册的 reducer 的类型信息,并且没有正确推断出 ApplicationState。
如果您的 selector 只涉及一个切片,那么他们不需要了解整个状态。他们只需要知道切片状态的类型,并知道从整个应用程序状态中提取该状态。
使用文档中的计数器示例,关键是如果我们将所有切片添加为顶级缩减器(未嵌套),那么我们知道应用程序状态满足 {counter: CounterState}
而我们不关心关于任何其他切片或它们的状态。
我使用了一些模式来实现它。我目前最喜欢的一种方法是为特定切片定义 select or,这样它们就可以 select 来自它们自己的切片状态。显然你不能用 selector 调用 useSelector
,所以我为每个切片创建了一个自定义挂钩。该挂钩实际上可以存在于该切片的文件夹中。
export const useCounterSelector = <T>(selector: (state: CounterState) => T): T =>
useSelector(({counter}: {counter: CounterState}) => selector(counter))
如果你要处理很多切片,你可以制作一个通用版本。在这里,我将切片本身作为参数传递进来,以获取名称(假设是它在主减速器中的键)和状态类型。
export const createUseSelector = <Name extends string, SliceState>(slice: Slice<SliceState, any, Name>) =>
<T>(selector: (state: SliceState) => T): T =>
useSelector((state: {[K in Name]: SliceState}) => selector(state[slice.name]))
export const useCounterSelector = createUseSelector(counterSlice);
// has inferred type <T>(selector: (state: CounterState) => T) => T
如何使用 react 和 redux store 解决 nx 工作空间中的循环依赖问题?
例如,如果我有一个包含所有商店配置的库,则有一个文件 createRootReducer - 它结合了我的减速器:
import {
someSliceReducer,
SOME_SLICE_FEATURE_KEY,
} from '@app/feature';
export const createRootReducer = (history: History) =>
combineReducers({
router: connectRouter(history),
form: formReducer,
[SOME_SLICE_FEATURE_KEY]: someSliceReducer,
});
商店库中的应用程序状态为:
import { createRootReducer } from './createRootReducer';
export type ApplicationState = ReturnType<ReturnType<typeof createRootReducer>>;
问题来自于在 someSliceReducer 所在的库中导入应用程序状态:
import {ApplicationState} from '@app/store'
const entities= useSelector(
(state: ApplicationState) => state.dischargeFolder.loadingStatus
);
现在我们有一个 循环依赖关系 并且 nx 警告我们:
Circular dependency between "feature" and "store" detected: feature -> store -> feature eslint@nrwl/nx/enforce-module-boundaries
如何避免这种情况?我需要在 root-reducer 中导入 reducer,但我还需要将 ApplicationState 导入到功能中。 我试图将 root-reducer 提取到自己的库中 - 但这并没有解决问题 nx 抱怨超过 3 个库的循环依赖。
我还尝试使用“reducerRegistry”,它接受一个 reducer 并在内部注册它 - 不幸的是,使用这种方法我丢失了已注册的 reducer 的类型信息,并且没有正确推断出 ApplicationState。
如果您的 selector 只涉及一个切片,那么他们不需要了解整个状态。他们只需要知道切片状态的类型,并知道从整个应用程序状态中提取该状态。
使用文档中的计数器示例,关键是如果我们将所有切片添加为顶级缩减器(未嵌套),那么我们知道应用程序状态满足 {counter: CounterState}
而我们不关心关于任何其他切片或它们的状态。
我使用了一些模式来实现它。我目前最喜欢的一种方法是为特定切片定义 select or,这样它们就可以 select 来自它们自己的切片状态。显然你不能用 selector 调用 useSelector
,所以我为每个切片创建了一个自定义挂钩。该挂钩实际上可以存在于该切片的文件夹中。
export const useCounterSelector = <T>(selector: (state: CounterState) => T): T =>
useSelector(({counter}: {counter: CounterState}) => selector(counter))
如果你要处理很多切片,你可以制作一个通用版本。在这里,我将切片本身作为参数传递进来,以获取名称(假设是它在主减速器中的键)和状态类型。
export const createUseSelector = <Name extends string, SliceState>(slice: Slice<SliceState, any, Name>) =>
<T>(selector: (state: SliceState) => T): T =>
useSelector((state: {[K in Name]: SliceState}) => selector(state[slice.name]))
export const useCounterSelector = createUseSelector(counterSlice);
// has inferred type <T>(selector: (state: CounterState) => T) => T