Open kettanaito opened 6 years ago
The only reason I find for this is for the field components to be really reusable anywhere in the code. That what you expect from the components you declare, not only form-related.
As a consequence of being formless, you won't be able to access fields
or form
in the callback methods, and the fields are going to be uncontrolled.
This change also means decentralization of the field events handling, and event callbacks.
As for now, any field interaction emits the respective event, the latter is being caught by the form observables, and being handled properly. Form is also the place responsible for dispatching various callback methods (i.e. onChange
, onFocus
) provided by the end developer to react to field updates. In case the form isn't present, there is:
I don't know how I feel about this overview. This most likely means a huge rework of the architecture, and I think it's not worth the trouble.
Alternatively, formless fields may be just super diminished versions of full-scale fields. I am okay with the changes if it's approximately like this:
if (this.context.form) {
return handleFieldAsNormal();
}
handleFieldAsFormless();
Summing things up.
Now the fields' state are kept in the form's state. Once the form is gone, formless field must contain its own state by itself.
Formless fields are stateful, containing their own field state.
All field state mutation actions (fieldChange, fieldBlur, etc.) are kept in the form. Formless field must use some other way of mutating the field's state.
I keep thinking of pure functions which take the current field state, additional data, and produce the next field state. This would be a functional way of form implementation. Then, the form component itself would reuse those pure functions as well.
A couple of pure function examples:
function handleFieldChange({ fieldProps, fields, form, nextValue }) {
return fieldProps.set(fieldProps.get('valuePropName'), nextValue);
}
function validateField({ fieldProps, fields, form }) {
const nextValidityState = fieldUtils.validate({ ... });
return fieldProps.merge(nextValidityState);
}
It has just occurred to me, that it is possible to understand whether the field is formless on the createField
high-order component level.
That way, in case of formless fields, HOC could act as a field's state accumulator, a replacement for Form in terms of field-form communication. This way field component remains as is, it keeps communicating up as is, as if there is always a form. Instead, createField
HOC gets smarter in case of formless fields.
@Vidlec In case you started to work on this feature, please align with me.
I'm preparing the architectural changes to RAF (#250), one of the points of which is to isolate the whole logic into bunch of pure functions. That will help tremendously to use the same composite handlers on the createField
wrapper, just as a form handles the field.
Let me know if anything!
Any news on this?
I just can't catch this thing – why React validation libs coerce us to use input
always within a form
element? Am I miss something?
I'd like to use createField
HOC as a generic common wrapper within a custom UI-kit components, unwrapped in any form at all.
Maybe renderless component, something like FormWrapper
, or another HOC e.g. withForm
should do the trick? it seems to be more convenient and flexible.
Big up and thanks for development this part of UI\UX with React!
Hi, @nickensoul. Thanks for the kind words! Let me update you.
The biggest task here is to replace the Form
as the event source hub. At the moment the Form
component establishes per-instance event emitter, and subscribes to certain events with handlers. Field component wrapped in createField
communicates back to the parent Form via form's event emitter to propagate such events as mounting/unmounting, value change, focus, or blur.
I would say that from the technical perspective a solution to support formless fields is somewhat clear. It would be good to implement (or prepare for) formless fields under #324. I'm currently working on #354, which improves event handlers that would grant less control to the Form, and more to the events.
I understand both a desire to use a form element without a wrapping Form, and a conceptual idea behind a form input (to gather data for a form). Nevertheless, I still think that formless fields is worth implementing, but I would also encourage developers to expect less functionality from a formless field.
This implementation is on the roadmap, but I would put #324 and #232 as the highest priority.
FormProvider
, or via custom HOC (to be discussed)Wow, appreciate such fast and detailed reply! Thanks, @kettanaito. Yep, I've understood points you've mentioned above and agree with them. I just need a one confirmation: as I understood, at this time, we shell use react-advanced-form as its current state – wrap fields in form; but in nearest future we'd like to refactor them after #324 (or later task) will be released? Is there are breaking changes expected?
Considering the limitations that @kettanaito has mentioned, I don’t think making any field formless should introduce any breaking changes, also I am assuming that it should respect the global validation rules and messages.
@nickensoul, yes, your understanding is correct.
We use RAF on production, and at the moment we wrap each field we tend to use outside of a form with an explicit Form component to ensure proper communication (such use cases are few, however). The future plan is to refactor this communication, which would potentially allow formless fields. As I've mentioned above, createField
itself is already a HOC, which can check if there is a parent form, and if not, it can serve as the events hub instead of a form. A proof of concept wouldn't hurt here.
True, @redraushan, it shouldn't be a breaking change. Communication updates and adoption of new context API will cause changes internally, but I would strive to sustain the existing API as-is. There is already a list of suggested API change proposals for 2.0
– #264, I would list any breaking change after this migration there.
What
Need to consider a formless usage of field components.
Why
Right now when a field component is rendered and is unable to find any ancestor Form, it will throw an error during the record registration. This may be confusing for the beginning developers.
However, it is also reasonable to insist to wrap fields in
Form
. Fields compose a form, so there must be a form. This suggestion requires discussion.Specification
<Form>
component.fields
andform
within any callback/handler methods. b) A formless field cannot accessfields
andform
in any validation resolvers. c) A formless field behaves as a plaininput
field. That implies, it is uncontrolled by default, and can be made controlled by providing avalue
prop and a change handler function. d) (???) A formless field can still accept field enhancers. e) A formless field doesn't benefit from any form behaviors (serialization, validation, etc.).