@payping/redux
v2.24.0-beta.14
Published
payping redux
Downloads
76
Keywords
Readme
This document has been updated to version 2.0.0
What is it
this package is meant to build a
redux
store
object with some default configs + payping redux actions & reducersplus it comes with
redux-persist
integration as an optional featureit uses
redux-thunk
&promise
as default middlewarespromise
middleware: it allows redux to use promisified actions
it also has
redux-devtools
&redux-logger
enabled whenNODE_ENV
is not equal to"production"
"test"
How to use
Initial work:
create a directory called
redux
in your app root dir andactions
,reducers
&configs
subdirectories in it.create
index.ts
file inredux/configs
just like the following code:
// root/redux/configs/index.ts
import { SdkConfigureStore } from "@payping/redux/store";
export const reduxConfig: SdkConfigureStore = {};
- At the
index.tsx
file in your app root dir, createstore
in it by passingreduxConfig
to theconfigureStore()
method
// root/index.tsx
import { configureStore } from "@payping/redux";
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import { reduxConfig } from "./redux/configs";
export const { store } = configureStore(reduxConfig);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
- export all actions from package in
redux/actions/index.ts
file:
// root/redux/actions/index.ts
export * from "@payping/redux/actions";
Assumptions:
By combining some of the following assumptions, you can build the store
object:
I don't want to use
redux-persist
and I have no custom redux configs or additional actions & reducers.I want to use
redux-persist
.I have some custom redux configs.
I have some additional actions or reducers.
Pick the instruction you need, from bellow:
Instructions:
whenever you needed to add some reducers to your redux, create a new interface in
redux/configs/index.ts
, calledAppStoreStates
which extendsSdkStoreStates
. then modifyconfigureStore(reduxConfig)
toconfigureStore<AppStoreStates>(reduxConfig)
. and istead ofSdkStoreStates
, useAppStoreStates
wherever you needed that.
use
SdkThunkDispatch
type whenever you want to add type for a dispatcher
- for assumption 1:
- you don't need to do anything
- for assumption 2:
- create
persistConfig.ts
file inredux/configs
just like the following code:
// root/redux/configs/persistConfig.ts
import { SdkPersistConfig } from "@payping/redux/store/persistConfig";
// use localForage for web & desktop, and AsyncStorage for react-native
import localForage as storage from "localforage";
// import AsyncStorage as storage from '@react-native-community/async-storage';
import env from "../env";
const { storeVersion } = env;
const persistConfig: SdkPersistConfig = {
storage,
version: storeVersion,
};
export default { ...persistConfig };
by default, it create persisted reducer with
stateReconciler: autoMergeLevel2
andversion: 2
options
change
version
option, whenever you changed the reducers architecture
you can add any other
redux-persist
related config (checkSdkPersistConfig
interface) you want to it.
- import and add
persistConfig
toredux/configs/index.ts
just like the following code:
// root/redux/configs/index.ts
import { SdkConfigureStore } from "@payping/redux/store";
import persistConfig from "./persistConfig";
export const reduxConfig: SdkConfigureStore = {
appPersistConfig: persistConfig
};
- wrap your
ReactDom.render()
in a function calledonRehydrated
in order to render the app after persisted redux store, rehydrated from storage. it's for preventing any issue in redux related logics. then, pass theonRehydrated
to theconfigureStore()
method.
// root/index.tsx
import { configureStore } from "@payping/redux";
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import { PersistGate } from "redux-persist/integration/react";
import { reduxConfig } from "./redux/configs";
// eslint-disable-next-line @typescript-eslint/no-use-before-define
export const { store, persistor } = configureStore({ ...reduxConfig, onRehydrated });
const onRehydrated = (): void => {
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>,
document.getElementById("root")
);
};
- for assumption 3:
- add your redux configs in
redux/configs/index.ts
. e.g. addingrouter
middleware:
- add your redux configs in
// root/redux/configs/index.ts
import { SdkStoreStates } from "@payping/redux/reducers";
import { SdkConfigureStore } from "@payping/redux/store";
import { RouterState, connectRouter, routerActions, routerMiddleware } from "connected-react-router";
import { LocationState, createHashHistory } from "history";
import { AnyAction, Reducer, StoreEnhancer } from "redux";
export interface AppStoreStates extends SdkStoreStates {
router: RouterState<LocationState>;
}
export const history = createHashHistory();
const router = routerMiddleware(history);
const appReducers = {
router: connectRouter(history) as Reducer<RouterState<LocationState>, AnyAction>,
};
const appMiddlewares = [router];
const composeActionCreators = { ...routerActions };
export const reduxConfig: SdkConfigureStore = {
appMiddlewares,
appReducers,
composeActionCreators
};
- for assumption 4:
define your actions and reducers like the samples at the end of this page in
redux/actions
orredux/reducers
respectively.export your actions in
redux/actions/index.ts
like below:
// root/redux/actions/index.ts
export * from "@payping/redux/actions";
export { logout, refreshToken, toggleLoggingIn } from "./appAuth";
- add your reducer in
appReducers
atredux/configs/index.ts
and add it toAppStoreStates
interface (implement interface if it doesn't exist).
// root/redux/configs/index.ts
import { SdkStoreStates } from "@payping/redux/reducers";
import { SdkConfigureStore } from "@payping/redux/store";
import appAuth, { AppAuthState } from "../reducers/appAuth";
export interface AppStoreStates extends SdkStoreStates {
appAuth: AppAuthState;
}
const appReducers = {
appAuth
};
export const reduxConfig: SdkConfigureStore = {
appReducers,
};
- modify
configureStore(reduxConfig)
toconfigureStore<AppStoreStates>(reduxConfig)
.
sample action
// root/redux/actions/appAuth.ts
import { CLEAR_LIST, LOGGED_OUT, LOGGED_IN, SdkThunkActionResult, SdkThunkDispatch } from "@payping/redux/reducers";
import {
LoggedInAction,
TOGGLE_LOGGING_IN,
ToggleLoggingInAction
} from "../reducers/appAuth";
function toggleLoggingIn(): ToggleLoggingInAction {
return {
type: TOGGLE_LOGGING_IN
};
}
function loggedIn(token: string, expiresIn: number): LoggedInAction {
return {
payload: { expiresIn, token },
type: LOGGED_IN
};
}
function logoutDispatchs(): SdkThunkActionResult<Promise<void>> {
return async (dispatch): Promise<void> => {
dispatch({ type: LOGGED_OUT });
};
}
export { toggleLoggingIn, loggedIn, logoutDispatchs };
sample reducer
// root/redux/reducers/appAuth.ts
import { LoggedOutAction } from "@payping/redux/reducers";
export const TOGGLE_LOGGING_IN = "TOGGLE_LOGGING_IN";
export const LOGGED_OUT = "LOGGED_OUT";
export const LOGGED_IN = "LOGGED_IN";
export interface AppAuthState {
isLoggingIn: boolean;
}
export interface ToggleLoggingInAction {
type: typeof TOGGLE_LOGGING_IN;
}
export interface LoggedInAction {
type: typeof LOGGED_IN;
payload: { token: string; expiresIn: number };
}
export type AuthActionTypes = ToggleLoggingInAction | LoggedInAction | LoggedOutAction;
export const initialState: AppAuthState = {
isLoggingIn: false
};
export default function appAuth(state = initialState, action: AuthActionTypes): AppAuthState {
if (action.type === TOGGLE_LOGGING_IN) {
return {
...state,
isLoggingIn: !state.isLoggingIn
};
}
if (action.type === LOGGED_IN) {
const { token, expiresIn } = action.payload;
return {
...state,
expiresIn,
token
};
}
if (action.type === LOGGED_OUT) {
return initialState;
}
return state;
}
Checking changes before Publish:
- Run script for building package on local (
customPrepublishOnly:app
orcustomPrepublishOnly:admin
). - Output will be in a
dist|distAdmin
folder at the root of the project. - Go to the project that you want to install this package in and install it locally:
yarn add ../redux/dist/ or yarn add ../redux/distAdmin/
NOTE: If your project has submodules you need to use the
-W
option inyarn add
command and replace the version of the package in all package.json files with this route../redux/dist/
.
How to Publish:
Admin:
Create a release branch for this new version (its name should be the new version that you want to publish plus admin for example
1.0.4-admin
):Edit
build_config/admin/package.json
version (pay attention to Semver)Run script for publishing package on registry:
NOTE: In your terminal you should be logged in at our registry at https://npmregistry.manatadbir.ir If you aren't, run:
npm logout npm login --registry=https://npmregistry.manatadbir.ir
yarn customPublish:admin
- Finish your release branch
Dashboard:
Create a release branch for this new version (its name should be the new version that you want to publish plus app for example
1.0.4-app
):Edit
build_config/app/package.json
version (pay attention to Semver)Run script for publishing package on registry:
NOTE: In your terminal you should be logged in at npm registry at https://registry.npmjs.org. If you aren't, run:
npm logout npm login
yarn customPublish:app
- Finish your release branch