Skip to content

Instantly share code, notes, and snippets.

@mariotacke
Created June 22, 2019 04:28
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 mariotacke/3d7ac70c6b8d35b87e9810b82ca85859 to your computer and use it in GitHub Desktop.
Save mariotacke/3d7ac70c6b8d35b87e9810b82ca85859 to your computer and use it in GitHub Desktop.
Redux + Typescript Samples
import { combineReducers } from 'redux';
import timeReducer from './time';
const rootReducer = combineReducers({
time: timeReducer,
});
export type AppState = ReturnType<typeof rootReducer>;
export default rootReducer;
import React, { ReactType } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './store';
const render = (Component: ReactType) => {
return ReactDOM.render(
<Provider store={store}>
<Component />
</Provider>,
document.getElementById('root')
);
};
render(App);
if (module.hot) {
module.hot.accept('./App', () => {
const NextApp = require('./App').default;
render(NextApp);
});
}
import { createStore, applyMiddleware } from 'redux';
import { createLogger } from 'redux-logger';
import rootReducer from './reducers';
const loggerMiddleware = createLogger({
collapsed: true,
});
const configureStore = (preloadedState = {}) => {
const middleware = [
// development only middleware
...(process.env.NODE_ENV !== 'production' ? [loggerMiddleware] : []),
];
const store = createStore(
rootReducer,
preloadedState,
applyMiddleware(...middleware),
);
if (process.env.NODE_ENV !== 'production' && module.hot) {
module.hot.accept('./reducers', () => store.replaceReducer(rootReducer));
}
return store;
};
const store = configureStore();
export default store;
import assert from 'assert';
import timeReducer, { TimeActions, tick, TICK } from '.';
describe('time reducer', () => {
describe('actions', () => {
it('should create an action to tick time', () => {
const time: number = 100;
const actualAction = tick(time);
const expectedAction = {
type: TICK,
currentTime: time,
};
assert.deepEqual(actualAction, expectedAction);
});
});
it('should return the initial state', () => {
const state = timeReducer(undefined, {} as TimeActions);
assert.deepEqual(state, {
currentTime: 0,
lastTime: 0,
});
});
it('should handle TICK', () => {
const state = timeReducer({
currentTime: 10,
lastTime: 0,
}, tick(50));
assert.deepEqual(state, {
currentTime: 50,
lastTime: 10,
});
});
});
export const TICK = 'time/TICK';
interface TickAction {
type: typeof TICK,
currentTime: number,
}
export type TimeActions = TickAction;
type TimeState = {
currentTime: number,
lastTime: number,
};
export function tick (currentTime: number): TimeActions {
return {
type: TICK,
currentTime,
};
}
const initialState: TimeState = {
currentTime: 0,
lastTime: 0,
};
export default function timeReducer(state = initialState, action: TimeActions): TimeState {
switch (action.type) {
case TICK:
return {
...state,
currentTime: action.currentTime,
lastTime: state.currentTime,
};
default:
return state;
}
}
import { AppState } from '..';
export const getTimeElapsedSinceLastUpdate = (state: AppState) =>
state.time.lastTime === 0 ? 0 : state.time.currentTime - state.time.lastTime;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment