Created
January 2, 2019 23:05
-
-
Save jjzazuet/44ea3b0350f373252ca967ab1623945f to your computer and use it in GitHub Desktop.
React with Redux in Typescript - wiring draft
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ======== Start with action definitions ======== */ | |
import {Action} from "redux"; | |
import {ThunkAction, ThunkDispatch} from "redux-thunk"; | |
import {RootState} from "gopher/state"; | |
export enum Ui { LOCK, ERROR } | |
export enum Auth { USER_LOAD_START, USER_LOAD_END, AUTH_RESTART } | |
export type ActionType = Ui | Auth; | |
export interface FluxAction<T extends ActionType, P = any> extends Action<T> { payload: P; } | |
export interface UiLock extends FluxAction<typeof Ui.LOCK, boolean> {} | |
export type AppAction = UiLock; // | whatever else... | |
type TA<T extends ActionType, P> = ThunkAction<Promise<P>, RootState, null, FluxAction<T, P>>; | |
export type TD<T extends ActionType, P> = ThunkDispatch<RootState, null, FluxAction<T, P>>; | |
export interface DispatchProps { dispatch: TD<ActionType, any>; } // to inject into connected React components | |
export const hit = <T extends ActionType, P>(type: T, params: P): TA<T, P> => // to execute all actions as chained promises | |
(dispatch) => { | |
dispatch({type, payload: params}); | |
return Promise.resolve(params); | |
}; | |
export const lockUi = (toggleState: boolean) => hit(Ui.LOCK, toggleState); | |
/* ======== Define base state and reducer ======== */ | |
import {Reducer} from "redux"; | |
import {AppAction, Ui} from "somewhere/actions"; | |
export interface UiState { | |
uiLocked: boolean; | |
} | |
const baseState: UiState = {uiLocked: false}; | |
export const baseReducer: Reducer<UiState, AppAction> = (state = baseState, action) => { | |
switch (action.type) { | |
case Ui.LOCK: | |
return {...state, uiLocked: action.payload}; | |
default: return state; | |
} | |
}; | |
/* ======== Assemble base state and store ======== */ | |
import {UiState} from "somewhere/reducer"; | |
export interface RootState { | |
base: UiState; | |
} | |
//// //// | |
import {applyMiddleware, combineReducers, createStore} from "redux"; | |
import {createLogger} from "redux-logger"; | |
import thunkMiddleware from "redux-thunk"; | |
import {baseReducer} from "somewhere/reducer"; | |
import {RootState} from "somewhere/state"; | |
const rootReducer = combineReducers<RootState>({ | |
base: baseReducer | |
}); | |
const createStoreWithMiddleware = applyMiddleware( | |
thunkMiddleware, createLogger() | |
)(createStore); | |
export default (initialState: RootState) => createStoreWithMiddleware(rootReducer, initialState); | |
/* ======== Create and connect a component to the Redux state tree ======== */ | |
import * as React from "react"; | |
import {connect} from "react-redux"; | |
import {ActionType, DispatchProps, lockUi, TD} from "somewhere/actions"; | |
import {UiState} from "somewhere/reducer"; | |
import {RootState} from "somewhere/state"; | |
class Hello extends React.Component<UiState & DispatchProps> { | |
public componentDidMount() { | |
const d = this.props.dispatch; | |
d(lockUi(true)).then((lol) => d(lockUi(!lol))); | |
} | |
public render() { | |
return <h1>Hello</h1>; | |
} | |
} | |
export default connect( | |
(rs: RootState): UiState => rs.base, | |
(dispatch: TD<ActionType, any>): DispatchProps => ({dispatch}) | |
)((Hello)); | |
/* ======== Mount the main app ======== */ | |
import * as React from "react"; | |
import * as ReactDOM from "react-dom"; | |
import {Provider} from "react-redux"; | |
import Hello from "somewhere/components/Hello"; | |
import configureStore from "somewhere/store"; | |
ReactDOM.render( | |
<Provider store={configureStore({} as any)}> | |
<Hello /> | |
</Provider>, document.getElementById("root") | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment