Skip to content

Instantly share code, notes, and snippets.

@tlaitinen
Last active November 6, 2017 13:20
Show Gist options
  • Select an option

  • Save tlaitinen/d1f9fbdf194fe75a1ad8988efe5c43e1 to your computer and use it in GitHub Desktop.

Select an option

Save tlaitinen/d1f9fbdf194fe75a1ad8988efe5c43e1 to your computer and use it in GitHub Desktop.
Redux reducer example (TypeScript)
import {ActionCreator} from 'react-redux-typescript';
import {ModalType} from './modals';
import {RootState, Dispatch} from '@src/reducers';
import {omitBy} from 'lodash';
export interface State {
readonly loading: boolean;
readonly messages: Readonly<{[messageId:string]:string}>,
readonly modals: ReadonlyArray<ModalType>
}
const defState:State = {
loading: true,
messages: {},
modals: []
};
export function getLoading(state:RootState) {
return state.ui.loading;
}
export function getMessages(state:RootState) {
return state.ui.messages;
}
export function getModal(state:RootState) {
let m = state.ui.modals;
if (m.length > 0) {
return m[m.length-1];
} else {
return null;
}
}
export const ActionCreators = {
SetLoading: new ActionCreator<'SetLoading', boolean>('SetLoading'),
ShowModal: new ActionCreator<'ShowModal', ModalType>('ShowModal'),
HideModal: new ActionCreator<'HideModal', void>('HideModal'),
AddMessage: new ActionCreator<'AddMessage', {messageId: string, message:string}>('AddMessage'),
RemoveMessage: new ActionCreator<'RemoveMessage', string>('RemoveMessage')
}
export function startLoading() {
return ActionCreators.SetLoading.create(true);
}
export function stopLoading() {
return ActionCreators.SetLoading.create(false);
}
export function wrapLoading(...promises:Promise<any>[]) {
return (dispatch:Dispatch) => {
dispatch(startLoading());
return Promise.all(promises).then(() => {
return dispatch(stopLoading());
}).catch(e => {
dispatch(stopLoading());
console.error(e);
});
};
}
type Action = typeof ActionCreators[keyof typeof ActionCreators];
let nextMessageId = 1;
export function message(message:string) {
return (dispatch:Dispatch) => {
const messageId = '' + (nextMessageId++);
dispatch(ActionCreators.AddMessage.create({messageId, message}));
setTimeout(() => dispatch(ActionCreators.RemoveMessage.create(messageId)), 5000);
};
}
export default function uiReducer(state:State = defState, action:Action) {
switch(action.type) {
case ActionCreators.SetLoading.type:
return {...state,
loading: action.payload
};
case ActionCreators.AddMessage.type:
return {...state,
messages: {
...state.messages,
[action.payload.messageId]: action.payload.message
}
};
case ActionCreators.RemoveMessage.type:
return {...state,
messages: omitBy(state.messages, (_v,k) => k === action.payload)
};
case ActionCreators.ShowModal.type:
return {...state,
modals: state.modals.concat(action.payload)
};
case ActionCreators.HideModal.type:
return {...state,
modals: state.modals.slice(0, -1)
};
default:
return state;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment