Source: app/enhanced-redux-form/components/EnhancedField.js

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { findDOMNode } from 'react-dom';
import Field from 'redux-form/lib/Field';
import debugLib from 'debug';
import { makeGetCustomValidationMeta } from '../reducers/validationReducer';

/**
 * @module enhanced-redux-form/components/EnhancedField
 */

const debug = debugLib('SlimmingWorld:EnhancedField');

const createEnhancedInputComponent = InputComponent => {
  const ConnectedInputComponent = connect(
    () => {
      const getCustomValidationMeta = makeGetCustomValidationMeta();

      return (state, props) => getCustomValidationMeta(state.enhancedForm.validation, props);
    },
    null,
    (stateProps, dispatchProps, ownProps) => ({
      ...ownProps,
      meta: {
        ...ownProps.meta,
        ...stateProps.meta,
      },
    }),
  )(InputComponent);

  /* eslint-disable no-underscore-dangle */
  const EnhancedInputComponent = (props, context) => (
    <ConnectedInputComponent {...props} form={context._reduxForm.form} />
  );
  EnhancedInputComponent.contextTypes = {
    _reduxForm: PropTypes.object.isRequired,
  };
  /* eslint-enable no-underscore-dangle */

  return EnhancedInputComponent;
};

/**
 * Should be used instead of the redux-form &lt;Field&gt; component to provide
 * enhanced-redux-form functionality to inputs. The API for this component is exactly the
 * same as the &lt;Field&gt; component. Please see the
 * {@link http://redux-form.com/6.3.1/docs/api/Field.md/|redux-form documentation}
 * for more info.
 * @class EnhancedField
 * @category forms
 */
class EnhancedField extends Component {
  state = {
    EnhancedInput: createEnhancedInputComponent(this.props.component),
  };

  componentDidMount() {
    this.context.registerWizardField && this.context.registerWizardField(this.props.name);

    const domNode = findDOMNode(this);
    if (domNode) {
      const input = domNode.querySelector(
        'input[type=text],input[type=email],input[type=password]',
      );
      if (input) {
        const { _reduxForm: formContext } = this.context;
        if (formContext) {
          const values = formContext.values || {};

          if (input.value && values[this.props.name] !== input.value) {
            formContext.dispatch(formContext.change(this.props.name, input.value));
          }
        }
      }
    }
  }

  componentDidUpdate({ component }) {
    if (component !== this.props.component) {
      debug('Ignored change of "component" prop. Prop cannot be changed after mount.');
    }
  }

  render() {
    const { EnhancedInput } = this.state;
    return EnhancedInput ? <Field {...this.props} component={EnhancedInput} /> : null;
  }
}

EnhancedField.propTypes = {
  // eslint-disable-next-line react/forbid-prop-types
  component: PropTypes.any.isRequired,
  name: PropTypes.string,
};

EnhancedField.contextTypes = {
  registerWizardField: PropTypes.func,
  _reduxForm: PropTypes.object.isRequired,
};

export default EnhancedField;