Skip to content

Instantly share code, notes, and snippets.

@ushiboy
Created October 6, 2018 13:13
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 ushiboy/c0f0392d2ffd0a1a4a8330c72ba7f803 to your computer and use it in GitHub Desktop.
Save ushiboy/c0f0392d2ffd0a1a4a8330c72ba7f803 to your computer and use it in GitHub Desktop.
Redux No combineReducer and reduce-reducer
/* @flow */
import '@babel/polyfill';
import { createStore, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
type AppState = {
counter: CounterState,
message: MessageState,
child: ChildState
}
type IncrementAction = { type: 'INCREMENT' };
type DecrementAction = { type: 'DECREMENT' };
type SendMessageAction = { type: 'SEND_MESSAGE', payload: { message: string } };
type ClearMessageAction = { type: 'CLEAR_MESSAGE' };
type Action =
| IncrementAction
| DecrementAction
| SendMessageAction
| ClearMessageAction
type Dispatch = (action: Action | ThunkAction ) => any;
type GetState = () => AppState;
type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
type CounterState = {
count: number;
}
function counter(state: CounterState = initCounter(), action : Action): CounterState {
switch (action.type) {
case 'INCREMENT': {
return Object.assign({}, state, {
count: state.count + 1
});
}
case 'DECREMENT': {
return Object.assign({}, state, {
count: state.count - 1
});
}
default:
return state;
}
}
function initCounter(): CounterState {
return {
count: 0
};
}
type MessageState = {
message: string
};
function message(state: MessageState = initMessage(), action: Action): MessageState {
switch (action.type) {
case 'SEND_MESSAGE': {
return Object.assign({}, state, {
message: action.payload.message
});
}
case 'CLEAR_MESSAGE': {
return Object.assign({}, state, {
message: ''
});
}
default: {
return state;
}
}
}
function initMessage(): MessageState {
return {
message: ''
};
}
type ChildState = {
value: number
};
function child(state: ChildState = initChild(), action: Action, counter: CounterState): ChildState {
const newValue = counter.count * 100;
if (state.value !== newValue) {
return Object.assign({}, state, {
value: newValue
});
}
return state;
}
function initChild(): ChildState {
return {
value: 0
};
}
const reducers = [
['counter', (s:AppState, a:Action) => counter(s.counter, a)],
['message', (s:AppState, a:Action) => message(s.message, a)],
['child', (s:AppState, a:Action) => child(s.child, a, s.counter)]
];
function reducer(state: AppState = initAppState(), action: Action): AppState {
let hasChanged = false;
const nextState = Object.assign({}, state);
reducers.forEach(([k, r]) => {
const prevStateForKey = state[k];
// $FlowFixMe
const nextStateForKey = r(nextState, action);
hasChanged = hasChanged || nextStateForKey !== prevStateForKey;
// $FlowFixMe
nextState[k] = nextStateForKey;
});
return hasChanged ? nextState : state;
}
function initAppState(): AppState {
return {
counter: initCounter(),
message: initMessage(),
child: initChild()
};
}
const store = createStore(reducer, applyMiddleware(ReduxThunk));
store.subscribe(() =>
console.log(JSON.stringify(store.getState()))
)
function wait(ms) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, ms);
});
}
function increment(): ThunkAction {
return async (dispatch) => {
await wait(1000);
return dispatch({
type: 'INCREMENT'
});
};
}
function decrement(): ThunkAction {
return async (dispatch) => {
await wait(1000);
return dispatch({
type: 'DECREMENT'
});
};
}
function sendMessage(message): ThunkAction {
return async (dispatch) => {
await wait(1000);
return dispatch({
type: 'SEND_MESSAGE',
payload: {
message
}
});
};
}
function clearMessage(): ThunkAction {
return async (dispatch) => {
await wait(1000);
return dispatch({
type: 'CLEAR_MESSAGE'
});
};
}
(async function() {
await store.dispatch(increment());
await store.dispatch(sendMessage('hello'));
await store.dispatch(increment());
await store.dispatch(clearMessage());
store.dispatch({ type: 'NONE' });
await store.dispatch(decrement());
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment