Skip to content

Instantly share code, notes, and snippets.

@alfonsodev
Last active September 6, 2020 10:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alfonsodev/558f7c80892386c7273342b64716d905 to your computer and use it in GitHub Desktop.
Save alfonsodev/558f7c80892386c7273342b64716d905 to your computer and use it in GitHub Desktop.
React stack
/* eslint-disable global-require */
/* eslint-disable no-undef */
import { compose } from "redux";
import persistState from "redux-localstorage";
import { StoreEnhancer } from "redux";
import { routerMiddleware } from "connected-react-router";
import { createBrowserHistory } from "history";
import { createEpicMiddleware } from "redux-observable";
import { createStore, applyMiddleware } from "redux";
import rootEpic from "./epics";
import rootReducer from "./reducers";
import { FirebaseUser } from "../auth/logic/User";
export const history = createBrowserHistory();
declare global {
interface Window {
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any;
}
}
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const epicMiddleware = createEpicMiddleware({
dependencies: {
user: new FirebaseUser(),
},
});
const rootEnhacer: StoreEnhancer = composeEnhancer(
applyMiddleware(routerMiddleware(history), epicMiddleware),
persistState(undefined, "token")
);
const store = createStore(rootReducer(history), rootEnhacer);
epicMiddleware.run(rootEpic);
export const dispatch = store.dispatch;
export default store;
import { combineEpics } from "redux-observable";
import { Observable, from } from "rxjs";
import { filter, map, switchMap } from "rxjs/operators";
import { Action, isActionOf } from "typesafe-actions";
import { createAction } from "typesafe-actions";
import { submitSignUpFormEpic } from "../auth/epics";
import displayErrorsEpic from "../errors/displayErrorsEpic";
const pingHandler = (): Promise<number> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(Date.now());
}, 2000);
});
};
export const pong = createAction("PONG")<number>();
export const ping = createAction("PING")();
const onAuthStateChangedEpic = (action$: Observable<Action>) =>
action$.pipe(
filter(isActionOf(ping)),
switchMap(() => from(pingHandler()).pipe(map((time) => pong(time))))
);
export default combineEpics(
...[onAuthStateChangedEpic, submitSignUpFormEpic, displayErrorsEpic]
);
import { initAuthState } from "../auth";
import { initNotificationsState } from "../notifications/store/NotificationsState";
export default {
auth: initAuthState,
notifications: initNotificationsState,
};
# for react state managment
yarn add redux-localstorage redux react-redux rxjs react immer
# for routing
yarn add connected-react-router history
mkdir src/app
touch src/app/{bootstrap,configureStore,epics,initialStoreState,reducers}.ts
# for database
yarn add @firebase/app @firebase/app-types @firebase/auth @firebase/firestore
import {
connectRouter,
RouterState,
LocationChangeAction,
} from "connected-react-router";
import produce from "immer";
import { History } from "history";
import { Reducer } from "typesafe-actions";
import { combineReducers } from "redux";
import notifications from "../notifications/reducers";
import { authReducer } from "../auth";
import AuthState from "../auth/store/AuthState";
const health: Reducer<any, any> = produce((draft, action) => {}, "ping");
interface AppReducers {
router: Reducer<
RouterState<History.PoorMansUnknown>,
LocationChangeAction<History.PoorMansUnknown>
>;
health: Reducer<any, any>;
notifications: Reducer<any, any>;
auth: Reducer<AuthState, any>;
}
export default (history: History) => {
const reducers: AppReducers = {
router: connectRouter(history),
health,
notifications,
auth: authReducer,
};
return combineReducers(reducers);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment