snowshoes
11/26/2017 - 9:25 PM

Use Redux Connect, with context in your map* methods!

Use Redux Connect, with context in your map* methods!

import { connect } from './connect-context'; // special connect-context (not an npm package, code below!)
import { PropTypes } from 'react';

const contextTypes = {
  valueFromContext: PropTypes.object.isRequired,
};

function mapStateToProps(state, ownProps, context) { /* .. */ }
function mapDispatchToProps(dispatch, ownProps, context) { /* .. */ }
function Component(props, context) { /* .. */ }


export default connect(mapStateToProps, mapDispatchToProps, contextTypes)(Component);
import React from 'react';
import { connect as reduxConnect } from 'react-redux';

function wrapWithContext(mapStateToProps, mapDispatchToProps, contextTypes, component) {
  return class ConnectedComponent extends React.Component {
    constructor(props, context) {
      super(props, context);

      /*
       * This is the magic right here!
       */
      this.mapStateToProps = mapStateToProps
        ? (state, ownProps) => mapStateToProps(state, ownProps, context)
        : null;
      this.mapDispatchToProps = mapDispatchToProps
        ? (dispatch, ownProps) => mapDispatchToProps(dispatch, ownProps, context)
        : null;
      this.component = reduxConnect(this.mapStateToProps, this.mapDispatchToProps)(component);

      // should we do this for other methods too?
      this.shouldComponentUpdate = this.component.shouldComponentUpdate;
    }

    static contextTypes = contextTypes;

    render() {
      const Component = this.component;
      return <Component {...this.props} />;
    }
  };
}

/**
 * Enhanced version of redux' connect that provides context to the map methods.
 *
 * @param {Function} mapStateToProps - The function to mapStateToProps
 * @param {Function} mapDispatchToProps - The function to mapDispatchToProps
 * @param {Object} contextTypes - Must adhere to the contextTypes-style object
 * @returns {Function} - returns a function that wraps a provided component with context
 *
 * This impl does not include `mergeProps` or `options` though you can easily add it by just passing it through.
 */
export default function connect(mapStateToProps, mapDispatchToProps, contextTypes) {
  return component => {
    return wrapWithContext(
      mapStateToProps,
      mapDispatchToProps,
      contextTypes,
      component
    );
  };
}