Must do prop transformation, it needs to add a specific onChange
handler to each control.
I dislike this immensly but it'll work with our existing components and is ugly enough to encourage us to move to something like Redux.
// import get from 'lodash/object/get'
const handleControlChange = (onChange, statePath) => (value) =>
onChange(statePath, value)
const StateControl = (Component) => React.createClass({
contextTypes: {
onChange: React.PropTypes.func,
parentState: React.PropTypes.object
},
render () {
const { statePath } = this.props
const { onChange, parentState } = this.context
return (
<Component
{ ...props }
value={ get(parentState, statePath) }
onChange={ handleControlChange(onChange, statePath) }
/>
)
}
})
// import set from 'lodash/object/set'
// import cloneDeep from 'lodash/object/cloneDeep'
const GenericStateContainer = React.createClass({
getInitialState () {
return {}
},
handleChange (statePath, value) {
const currentState = cloneDeep(this.state)
const newState = set(currentState, statePath, value)
this.setState(newState, () => {
this.props.onChange(this.state)
})
},
childContextTypes: {
onChange: React.PropTypes.func,
parentState: React.PropTypes.object
},
getChildContext: function() {
return {
onChange: this.handleChange,
parentState: this.state
}
},
render () {
return (
<div>
{ this.props.children }
</div>
)
}
})
const ControlledTextInput = StateControl(TextInput)
const StatefulTextInput = React.createClass({
render () {
return (
<GenericStateContainer>
<ControlledTextInput statePath="value" />
</GenericStateContainer>
)
}
})
const StatefulFieldset = React.createClass({
render () {
return (
<GenericStateContainer>
<ControlledTextInput statePath="user.first_name" />
<ControlledTextInput statePath="user.last_name" />
</GenericStateContainer>
)
}
})
Allows us to go:
const ControlledSomething = StateControl(AnythingWithOnChangeAndValueProps)
// ...
<GenericStateContainer>
<ControlledSomething statePath="something, maybe default to `value`" />
</GenericStateContainer>
Whenever the thing needs state.
It's made a little more convulated because we can have multiple children updating the state of one generic container...
This is in lieu of having "solved" data flow.