Skip to content

Instantly share code, notes, and snippets.

@tlaitinen
Last active June 8, 2018 07:33
Show Gist options
  • Select an option

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

Select an option

Save tlaitinen/1c680df7300375bbb60b18e84efc601a to your computer and use it in GitHub Desktop.
import {connect} from 'react-redux';
import {Dispatch, bindActionCreators, ActionCreatorsMapObject} from 'redux';
import {createStandardAction} from 'typesafe-actions';
import React from 'react';
interface RootState {
counters: {
[name: string]: {count: number};
};
}
const actions = {
incrementByName: createStandardAction('INC')<string>()
};
export interface PropsMapper<StateProps, DispatchProps, OwnProps> {
fromState: (state:RootState, ownProps:OwnProps) => StateProps;
actions: (ownProps:OwnProps) => DispatchProps;
}
export type PropsOf<T> = T extends PropsMapper<infer StateProps, infer DispatchProps, infer OwnProps>
? StateProps & DispatchProps & OwnProps
: never;
export function appConnect<StateProps, DispatchProps extends ActionCreatorsMapObject, OwnProps>(mapper:PropsMapper<StateProps, DispatchProps, OwnProps>) {
return connect<StateProps, DispatchProps, OwnProps, RootState>(
mapper.fromState,
(dispatch:Dispatch<RootState>, ownProps:OwnProps) => bindActionCreators(mapper.actions(ownProps), dispatch)
);
}
type OwnProps = {name:string};
const propsMapper = {
fromState: (state: RootState, ownProps: OwnProps) => ({
count: state.counters[ownProps.name].count
}),
actions: (ownProps: OwnProps) => ({
inc() {
return actions.incrementByName(ownProps.name);
}
})
};
const Counter = ({inc, count}:PropsOf<typeof propsMapper>) => (
<button onClick={inc}>
{count}
</button>
)
export default appConnect(propsMapper)(Counter);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment