Hey guys,
I would be interested to see hooks here!
Well, there's this.

The problem, as I see it, is that hooks require your entire containing component to rerender, which negates the benefits of having a separate Field component that can rerender on its own without having to rerender the entire form.
There is still more investigation to be done, though.
@erikras That's awesome! Please, provide us with some benchmarks.
@erikras What do you think about this (I've modified your one)
I have updated my example. Now it is more simple (no handleSubmit and auto ContextProvider).
@gokalina IMHO, I don't think providing render as a key in an object to some "field constructor" is much better than render props.
My conclusion (at the moment) is that if you're going to embrace hooks, you will have to give up "individual field rerendering", which was one of RFF's primary goals. With something like react-final-form-hooks.
@erikras thank you for your answer. I agree with you, later I came to a conclusion that render in hook is no better than render props at all.
For individual field rendering I can see only one way - individual field components with useField hook (different from your implementation). In current project we have such components (for input, select, datepicker etc). With hooks it can be more clear:
function InputField({ name, subscription, ...restProps}) {
// Field component can pass own settings to useField
const { input, meta } = useField({ name, subscription, parse: parseImpl });
// and use field props before component tree
const shouldDisplayError = ...;
return (...);
}
...
<InputField name="firstname" placeholder="Enter first name..." />
...
In perfect word react-final-form should be built on top of react-final-form-hooks without API changes. And three of them (final-form, react-final-form and react-final-form-hooks) should live in peace.
I don't think hooks are the right abstraction for Form, or, at least, not alone. There are a number of trade-offs in react-final-form-hooks (passing around a form object, frequent rerendering, incompatibility with other react-final-form libraries) that I do not think are palatable. What do you think of an API like
import {FormProvider, useField, useForm, useFormSpy} from 'react-final-form';
function MyForm() {
// Doesn't get values, doesn't update (or rerender) on form state changing.
const {form, handleSubmit} = useForm({onSubmit, validate});
return (
// Provides `form` as context.
<FormProvider form={form}>
<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
<MyField name="firstName" placeholder="First Name" />
</div>
<div>
<label>Last Name</label>
<MyField name="lastName" placeholder="Last Name" />
</div>
<MyButton>Submit</MyButton>
</form>
</FormProvider>
);
}
// Has to be a separate component to properly consumer context. Maybe. Probably.
function MyField(props) {
const {placeholder, name} = props;
// Gets `form` from context.
const field = useField(name);
return (
<>
<input {...field.input} placeholder={placeholder} />
{field.meta.touched && field.meta.error && (
<span>{field.meta.error}</span>
)}
</>
);
}
function MySubmitButton(props) {
const {children} = props;
// Gets `form` from context.
const {pristine, submitting} = useFormSpy({pristine: true, submitting: true});
return (
<button disabled={pristine || submitting} type="submit">
{children}
</button>
);
}
It seems that this one can be closed, since react-final-form v5 introduces hooks.
Just one question: do the react-final-form implementation of hooks suffer from the same performance problems as react-final-form-hooks?
No. A component using useField() with a subscription will only rerender when the things it's subscribed to change.
More reading: https://github.com/final-form/react-final-form-hooks#whats-the-difference-between-react-final-form-hooks-and-the-hooks-introduced-in-react-final-form-v5
Thanks a lot!
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
Well, there's this.
The problem, as I see it, is that hooks require your entire containing component to rerender, which negates the benefits of having a separate
Fieldcomponent that can rerender on its own without having to rerender the entire form.There is still more investigation to be done, though.