redux#ReducersMapObject TypeScript Examples

The following examples show how to use redux#ReducersMapObject. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: handlePlugin.ts    From reactant with MIT License 7 votes vote down vote up
handlePlugin: HandlePlugin = (
  service: any,
  pluginHooks: PluginHooks
) => {
  if (service instanceof PluginModule) {
    if (typeof service.beforeCombineRootReducers === 'function') {
      pluginHooks.beforeCombineRootReducers.push(
        (reducers: ReducersMapObject) =>
          service.beforeCombineRootReducers!(reducers)
      );
    }
    if (typeof service.afterCombineRootReducers === 'function') {
      pluginHooks.afterCombineRootReducers.push((rootReducer: Reducer) =>
        service.afterCombineRootReducers!(rootReducer)
      );
    }
    if (typeof service.preloadedStateHandler === 'function') {
      pluginHooks.preloadedStateHandler.push(
        (preloadedState: PreloadedState<any>) =>
          service.preloadedStateHandler!(preloadedState)
      );
    }
    if (typeof service.enhancer === 'function') {
      pluginHooks.enhancer.push(service.enhancer.bind(service));
    }
    if (typeof service.middleware === 'function') {
      pluginHooks.middleware.push(service.middleware.bind(service));
    }
    if (typeof service.afterCreateStore === 'function') {
      pluginHooks.afterCreateStore.push(service.afterCreateStore.bind(service));
    }
    if (typeof service.provider === 'function') {
      pluginHooks.provider.push(service.provider.bind(service));
    }
  }
}
Example #2
Source File: router.tsx    From reactant with MIT License 7 votes vote down vote up
beforeCombineRootReducers(reducers: ReducersMapObject): ReducersMapObject {
    if (!this.autoCreateHistory) return reducers;
    if (Object.prototype.hasOwnProperty.call(reducers, this.stateKey)) {
      throw new Error(
        `The identifier '${this.stateKey}' has a duplicate name, please reset the option 'stateKey' of 'ReactantRouter' module.`
      );
    }
    return Object.assign(reducers, {
      [this.stateKey]: connectRouter(this.history),
    });
  }
Example #3
Source File: storage.tsx    From reactant with MIT License 7 votes vote down vote up
beforeCombineRootReducers(reducers: ReducersMapObject): ReducersMapObject {
    for (const [_, set] of this.storageSettingMap) {
      set();
    }
    Object.keys(reducers).forEach((key) => {
      const isTempIdentifier = /^@@reactant\//.test(key);
      if (isTempIdentifier) {
        this.blacklist.push(key);
      }
      const persistConfig = this.persistConfig[key];
      if (persistConfig) {
        const reducer = persistReducer(persistConfig, reducers[key]);
        Object.assign(reducers, {
          [key]: reducer,
        });
      } else if (this.persistRootConfig.blacklist) {
        // use blacklist mode
        if (isTempIdentifier) {
          if (__DEV__) {
            console.warn(
              `For state persistence, The '@injectable({ name })' in the ${key} module has not been set yet.`
            );
          }
        }
      }
    });
    return reducers;
  }
Example #4
Source File: lastAction.ts    From reactant with MIT License 5 votes vote down vote up
beforeCombineRootReducers(reducers: ReducersMapObject): ReducersMapObject {
    if (Object.prototype.hasOwnProperty.call(reducers, this.stateKey)) {
      throw new Error(
        `The identifier '${this.stateKey}' has a duplicate name, please reset the option 'stateKey' of 'LastAction' module.`
      );
    }
    return Object.assign(reducers, {
      [this.stateKey]: (
        _state: ILastActionState | null = null,
        {
          _inversePatches,
          state,
          rehydrate,
          register,
          ...action
        }: ILastActionState & { rehydrate: any; register: any }
      ) => {
        // ignore redux-persist property function in the action
        const rehydrateObj =
          typeof rehydrate === 'function' ||
          typeof rehydrate === 'undefined' ||
          rehydrate === null
            ? {}
            : { rehydrate };
        const registerObj =
          typeof register === 'function' ||
          typeof register === 'undefined' ||
          register === null
            ? {}
            : { register };
        // ignore inversePatches and state
        const reactantObj =
          action._reactant === actionIdentifier
            ? {}
            : { state, _inversePatches };
        return {
          ...action,
          ...rehydrateObj,
          ...registerObj,
          ...reactantObj,
          _sequence: (_state?._sequence ?? 0) + 1,
        };
      },
    });
  }
Example #5
Source File: plugin.ts    From reactant with MIT License 5 votes vote down vote up
// TODO: beforeCombineReducers & afterCombineReducers

  /** As hook before combine rootReducers */
  beforeCombineRootReducers?(reducers: ReducersMapObject): ReducersMapObject;
Example #6
Source File: createStore.ts    From reactant with MIT License 4 votes vote down vote up
export function createStore<T = any>({
  modules,
  container,
  ServiceIdentifiers,
  loadedModules,
  load,
  pluginHooks,
  preloadedState,
  devOptions = {},
  originalStore,
  beforeReplaceReducer,
  modulesMap = {},
}: CreateStoreOptions<T>): ReactantStore {
  let isExistReducer = false;
  let store: ReactantStore | undefined = originalStore;
  let reducers: ReducersMapObject = {};
  const subscriptions: Subscriptions = [];
  // TODO: replace with `mutative`
  const enableAutoFreeze = devOptions.autoFreeze ?? true;
  const enableReduxDevTools = devOptions.reduxDevTools ?? __DEV__;
  const enablePatches = devOptions.enablePatches ?? false;
  if (typeof store === 'undefined') {
    setAutoFreeze(enableAutoFreeze);
    if (enablePatches) {
      enablePatchesWithImmer();
    }
  }

  // add Non-dependent `modules` to ServiceIdentifiers config.
  for (const module of modules) {
    const moduleIdentifier =
      typeof module === 'function' ? module : module.provide;
    if (!ServiceIdentifiers.has(moduleIdentifier)) {
      ServiceIdentifiers.set(moduleIdentifier, []);
    }
  }
  for (const [Service] of ServiceIdentifiers) {
    // `Service` should be bound before `createStore`.
    if (container.isBound(Service) && !loadedModules.has(Service)) {
      const services: IService[] = container.getAll(Service);
      loadedModules.add(Service);
      services.forEach((service, index) => {
        if (typeof service !== 'object' || service === null) {
          return;
        }
        handlePlugin(service, pluginHooks);
        const isPlainObject =
          toString.call(service[stateKey]) === '[object Object]';
        const className = (Service as Function).name;
        let identifier: string | undefined = service[nameKey];
        // The `options.name` property of the decorator `@injectable(options)` parameter must be specified as a string, otherwise a staged string will be generated.
        // this solution replaces the `combineReducers` need `Object.keys` get keys without `symbol` keys.
        identifier ??= getStageName(className);
        if (typeof identifier !== 'string') {
          if (__DEV__) {
            console.error(`
                Since '${className}' module has set the module state, '${className}' module must set a unique and valid class property 'nameKey' to be used as the module index.
                Example:
                  @injectable({ name: 'fooBar' }) // <- add identifier for modules.
                  class FooBar {}
              `);
          } else {
            throw new Error(
              `'${className}' module 'options.name' property in '@injectable(options)' should be defined as a valid 'string'.`
            );
          }
        }
        if (services.length > 1) {
          // injection about multi-instances
          identifier += `:${index}`;
        }
        if (modulesMap[identifier]) {
          throw new Error(
            `'${className}' module name '${identifier}' property and other module conflicts.`
          );
        }
        Object.assign(modulesMap, {
          [identifier]: service,
        });
        if (isPlainObject) {
          const isEmptyObject = Object.keys(service[stateKey]!).length === 0;
          if (!isEmptyObject) {
            const descriptors: Record<string, PropertyDescriptor> = {};
            for (const key in service[stateKey]) {
              const descriptor = Object.getOwnPropertyDescriptor(service, key);
              // eslint-disable-next-line no-continue
              if (typeof descriptor === 'undefined') continue;
              Object.assign(service[stateKey], {
                [key]: descriptor.value,
              });
              descriptors[key] = {
                enumerable: true,
                configurable: false,
                get(this: ThisService) {
                  return this[stateKey]![key];
                },
                set(this: ThisService, value: unknown) {
                  this[stateKey]![key] = value;
                },
              };
            }

            const initState = enableAutoFreeze
              ? produce({ ...service[stateKey] }, () => {}) // freeze init state
              : service[stateKey]!;
            const serviceReducers = Object.keys(initState).reduce(
              (serviceReducersMapObject: ReducersMapObject, key) => {
                const value = initState[key];
                // support pure reducer
                if (typeof value === 'function') {
                  const pureReducer: Reducer = value;
                  const _initState = pureReducer(undefined, {} as AnyAction);
                  const reducer = (
                    state = _initState,
                    action: ReactantAction
                  ) => {
                    return action._reactant === actionIdentifier &&
                      action.state[identifier!]
                      ? action.state[identifier!][key]
                      : pureReducer(state, action);
                  };
                  return Object.assign(serviceReducersMapObject, {
                    [key]: reducer,
                  });
                }
                const reducer = (state = value, action: ReactantAction) => {
                  return action._reactant === actionIdentifier &&
                    action.state[identifier!]
                    ? action.state[identifier!][key]
                    : state;
                };
                return Object.assign(serviceReducersMapObject, {
                  [key]: reducer,
                });
              },
              {}
            );
            isExistReducer = true;
            const reducer = combineReducers(serviceReducers);
            Object.assign(reducers, {
              [identifier]: reducer,
            });
            Object.defineProperties(service, descriptors);
            // redefine get service state from store state.
            Object.defineProperties(service, {
              [stateKey]: {
                enumerable: false,
                configurable: false,
                get() {
                  const stagedState = getStagedState();
                  if (stagedState) return stagedState[identifier!];

                  const currentState = store!.getState()[identifier!];
                  if (enableAutoFreeze && !Object.isFrozen(currentState)) {
                    return Object.freeze(currentState);
                  }
                  return currentState;
                },
              },
            });
          } else {
            throw new Error(`
            '${className}' class property 'state' must have at least one state key.
          `);
          }
        }
        if (Array.isArray(service[subscriptionsKey])) {
          subscriptions.push(...service[subscriptionsKey]!);
        }
        Object.defineProperties(service, {
          [modulesKey]: {
            enumerable: false,
            configurable: false,
            writable: false,
            value: modulesMap,
          },
          [identifierKey]: {
            enumerable: false,
            configurable: false,
            writable: false,
            value: identifier,
          },
          // in order to support multiple instances for stores.
          [storeKey]: {
            enumerable: false,
            configurable: false,
            get() {
              return store;
            },
          },
          [containerKey]: {
            enumerable: false,
            configurable: false,
            get() {
              return container;
            },
          },
          // loader for dynamic modules.
          [loaderKey]: {
            enumerable: false,
            configurable: false,
            value(...args: Parameters<Loader>) {
              load(...args);
            },
          },
          // enablePatches options for immer
          [enablePatchesKey]: {
            enumerable: false,
            configurable: false,
            value: enablePatches,
          },
        });
      });
    }
  }
  if (typeof store === 'undefined') {
    // load reducers and create store for Redux
    const reducer = isExistReducer
      ? combineReducers(
          (reducers = perform(pluginHooks.beforeCombineRootReducers, reducers))
        )
      : () => null;
    const composeEnhancers = getComposeEnhancers(
      enableReduxDevTools,
      devOptions.reduxDevToolsOptions
    );
    store = createStoreWithRedux(
      perform(pluginHooks.afterCombineRootReducers, reducer),
      perform(
        pluginHooks.preloadedStateHandler,
        preloadedState
          ? Object.entries(preloadedState).reduce<Record<string, any>>(
              (state, [key, value]) =>
                modulesMap[key]
                  ? Object.assign(state, {
                      [key]: value,
                    })
                  : state,
              {}
            )
          : preloadedState
      ),
      composeEnhancers(
        applyMiddleware(...pluginHooks.middleware),
        ...pluginHooks.enhancer
      )
    );
    if (isExistReducer) {
      Object.assign(store, {
        reducers,
      });
    }
    perform(pluginHooks.afterCreateStore, store);
  } else if (isExistReducer) {
    // just load reducers
    store.reducers = {
      ...store.reducers,
      ...perform(pluginHooks.beforeCombineRootReducers, reducers),
    };
    const reducer = combineReducers(store.reducers!);
    const rootReducer = perform(pluginHooks.afterCombineRootReducers, reducer);
    if (typeof beforeReplaceReducer === 'function') {
      beforeReplaceReducer();
    }
    store.replaceReducer(rootReducer);
  } else if (typeof beforeReplaceReducer === 'function') {
    // TODO: refactor hook
    beforeReplaceReducer();
  }
  perform(subscriptions);
  return store;
}