react-redux-ts
Typescript wrapper around redux and react-redux that simplifies workflow
npm i react-redux-ts
1. Simple set
Adds a common action to set any value in the store via dispatch with typechecks. Without async:
store.setStateProp({
prop: 'myProp',
payload: 'val'
});
And async (similar to Redux-thunk):
store.setStatePropAsync({
prop: 'myProp',
func: myAsyncFunction
});
Will ensure that 'payload' in SET_PROP and return value of 'func' in SET_PROP_ASYNC has the same type as property in the store.
Async version will also dispatch notifications in order:
- start
- success / error
- end
Will also add both methods as props to connected react component
props.setStateProp(/* { ... } */);
props.setStatePropAsync(/* { ... } */);
2. Type actions
Allows to use type definitions as actions instead of objects.
actions.ts:
import { StateType } from '../store';
type ClearTodosAction = {
type: 'CLEAR_TODOS';
};
type SetVisibilityFilter = {
type: 'SET_VISIBILITY_FILTER';
filter: StateType['filter'];
};
export type ActionTypes = ClearTodosAction | SetVisibilityFilter;
customReducer.ts:
import { ActionTypes } from '../actions';
import { StateType } from '../store';
export function customReducer(state: StateType, action: ActionTypes): StateType {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return {
...state,
filter: action.filter
}
case 'CLEAR_TODOS':
return {
...state,
todos: []
}
default:
return state;
}
};
store.ts:
import { createStore } from 'react-redux-ts';
import { ActionTypes } from './actions';
import { customReducer } from './customReducer';
class State {
todos: string[] = [];
filter: 'SHOW_ALL' | 'HIDE_ALL' = 'SHOW_ALL';
myProp: string = '';
}
// All arguments of createStore are optional. It accepts your root reducer, initial state,
// boolean for whether or not use devtools, array of middlewares.
export const store = createStore<State, ActionTypes<State>>(
customReducer, new State());
export type DispatchType = typeof store.dispatch;
export type StoreAction = ReturnType<typeof store.dispatch>;
export type StateType = typeof State;
AppComponent.tsx:
import { connect, PropsType } from 'react-redux-ts';
import { StateType, DispatchType } from './store.ts';
type OwnPropsType = {};
const mapStateToProps = (state: StateType, ownProps: OwnPropsType) => {
return {
myProp: state.myProp
}
}
const mapDispatchToProps = (dispatch: DispatchType, ownProps: OwnPropsType) => {
return {
clearTodos: () => dispatch({ type: 'CLEAR_TODOS' })
}
}
type AppComponentPropsType = PropsType<StateType, OwnPropsType,
ReturnType<typeof mapStateToProps>, ReturnType<typeof mapDispatchToProps>>;
const AppComponent = (props: AppComponentPropsType) => {
return (
<div
onClick={() => {
props.setStateProp({
prop: 'myProp',
payload: 'val'
});
props.clearTodos();
}}
>{props.myProp}</div>
)
}
const connectedComponent = connect(mapStateToProps, mapDispatchToProps)(AppComponent);
export default connectedComponent;
index.tsx:
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux-ts'
import store from './store'
import AppComponent from './AppComponent'
const rootElement = document.getElementById('root');
ReactDOM.render(
<Provider store={store}>
<AppComponent />
</Provider>,
rootElement
);