mpen
mpen

Reputation: 282845

How to add context to recompose's withHandlers()?

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

Answers (1)

Renaud
Renaud

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

Related Questions