Skip to content

Instantly share code, notes, and snippets.

@pbadenski
Created August 23, 2019 09:06
Show Gist options
  • Save pbadenski/7321ef305faafd9e220e862262b8b521 to your computer and use it in GitHub Desktop.
Save pbadenski/7321ef305faafd9e220e862262b8b521 to your computer and use it in GitHub Desktop.
refract-react-redux connect
import React, { Context } from "react";
import {
InferableComponentEnhancerWithProps,
MapDispatchToPropsFunction,
MapStateToProps
} from "react-redux";
import { Aperture, toProps, withEffects } from "refract-rxjs";
import { combineLatest, concat, Observable, of } from "rxjs";
import { auditTime, first, map, startWith } from "rxjs/operators";
import { auditMap, connect as connect_ } from "rxjs-redux";
import { defaultMemoize } from "reselect";
export const ObservableStoreContext: Context<any> = React.createContext({});
const mergeProps = <TStateProps, TDispatchProps, TOwnProps, TMergedProps>(
stateProps: TStateProps,
dispatchProps: TDispatchProps,
ownProps: TOwnProps
): TStateProps & TDispatchProps & TOwnProps => {
return {
...stateProps,
...dispatchProps,
...ownProps
};
};
export const connect = <TStateProps = {}, TDispatchProps = {}, TOwnProps = {}, TState = {}>(
mapStateToProps: MapStateToProps<TStateProps, TOwnProps, TState> = () => ({} as TStateProps),
mapDispatchToProps: MapDispatchToPropsFunction<TDispatchProps, TOwnProps> = () => ({} as TDispatchProps)
): InferableComponentEnhancerWithProps<TStateProps & TDispatchProps & TOwnProps, TOwnProps> => {
type Props = TStateProps & TDispatchProps & TOwnProps;
type Context<TState> = { state$: Observable<TState>, dispatch: any };
const aperture: Aperture<Props, {}, Context<TState>> = (component, initialProps, initialContext) => {
const { state$, dispatch } = initialContext;
if (!state$ || !dispatch) {
throw new Error("$state or dispatch missing in the context");
}
const stateToProps = defaultMemoize(mapStateToProps);
const dispatchToProps = defaultMemoize(mapDispatchToProps);
return combineLatest([
component.observe<TOwnProps>().pipe(startWith(undefined)),
state$
]).pipe(
auditMap(([ownProps, state]) =>
of(mergeProps(
stateToProps(state, ownProps),
dispatchToProps(dispatch, ownProps),
ownProps
))
),
connect_(props => {
return props;
}),
map(toProps),
);
};
return withEffects(aperture, { Context: ObservableStoreContext }) as any;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment