import React, {Component, PropTypes} from 'react'
import hoistStatics from 'hoist-non-react-statics'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import * as importedActions from './actions'
import bindActionData from './bindActionData'
const getDisplayName = Comp => Comp.displayName || Comp.name || 'Component'
/**
* The decorator that is the main API to redux-form
*/
const createReduxForm =
structure =>
initialConfig => {
const config = {
touchOnBlur: true,
touchOnChange: false,
destroyOnUnmount: true,
getFormState: state => structure.getIn(state, 'form'),
...initialConfig
}
return WrappedComponent => {
class ReduxForm extends Component {
constructor(props) {
super(props)
}
getChildContext() {
return {
_reduxForm: {
...this.props,
getFormState: state => structure.getIn(this.props.getFormState(state), this.props.form),
submitPassback: submit => this.submit = submit
}
}
}
submit() {
throw new Error('You must include at least one submit button in your form')
}
render() {
// remove some redux-form config-only props
const {reduxMountPoint, destroyOnUnmount, form, getFormState, touchOnBlur, touchOnChange,
...passableProps } = this.props // eslint-disable-line no-redeclare
return <WrappedComponent {...passableProps}/>
}
}
ReduxForm.displayName = `ReduxForm(${getDisplayName(WrappedComponent)})`
ReduxForm.WrappedComponent = WrappedComponent
ReduxForm.childContextTypes = {
_reduxForm: PropTypes.object.isRequired
}
ReduxForm.propTypes = {
destroyOnUnmount: PropTypes.bool,
form: PropTypes.string.isRequired,
getFormState: PropTypes.func,
touchOnBlur: PropTypes.bool,
touchOnChange: PropTypes.bool
}
ReduxForm.defaultProps = config
const connector = connect(
undefined, // don't subscribe to ANYTHING!
(dispatch, ownProps) =>
bindActionCreators(
bindActionData({
...importedActions,
blur: bindActionData(importedActions.blur, {
touch: !!ownProps.touchOnBlur
}),
change: bindActionData(importedActions.change, {
touch: !!ownProps.touchOnChange
})
},
{ form: ownProps.form }),
dispatch)
)
return hoistStatics(connector(ReduxForm), WrappedComponent)
}
}
export default createReduxForm
|