Reputation: 282845
recompose
has this function called withHandlers
that lets you define an event handler while keeping your component pure.
e.g. if you had something like this inside you render()
method:
<TextInput value={value} onChange={ev => this.handleChange(ev.target.value)} />
it wouldn't be pure because every time your component renders, it'd by passing a different onChange
function to your TextInput
component.
This is great, but how can this be extended to support arrays of inputs? Or otherwise provide auxiliary data?
e.g. taking their example and extending it a bit:
const enhance = compose(
withState('values', 'updateValue', ''),
withHandlers({
onChange: props => inputName => event => {
props.updateValue(inputName, event.target.value)
},
onSubmit: props => event => {
event.preventDefault();
submitForm(props.value)
}
})
)
const Form = enhance(({ value, onChange, onSubmit, inputs }) =>
<form onSubmit={onSubmit}>
<label>Value
{inputs.map(input => (
<TextInput value={value} onChange={onChange(input)} />
))}
</label>
</form>
)
I've fudged the details a bit, but pretend inputs
comes in as an array of input names. e.g. ["firstName","lastName"]
would render two textboxes, one for each.
I want to store the values for each of these in my state, but I don't want to define separate updater functions for each. Thus I need to attach some metadata to the onChange={...}
prop so that I know which field I'm updating in my state.
How can I do that?
In my example I wrote onChange(input)
and added an extra 'level' to the withHandlers.onChange
function to accept the extra argument, but withHandlers
doesn't actually work that way. Is there some way to do this -- i.e., ensure that each TextInput
receives the same function instance every time <Form>
is rendered?
Upvotes: 0
Views: 1016
Reputation: 1300
That's a typical case where you need to define the change handle directly inside your TextInput component. You'd need to pass updateValue function as a prop to TextInput components.
Upvotes: 2