react-final-form icon indicating copy to clipboard operation
react-final-form copied to clipboard

Add a nicer API to Perform Form actions outside of render

Open dawidcxx opened this issue 5 years ago • 5 comments

Are you submitting a bug report or a feature request?

feature request

What is the current behavior?

Currently you have to stuff that feels hacky https://github.com/final-form/react-final-form/blob/master/docs/faq.md#how-can-i-trigger-a-submit-from-outside-my-form

With hooks out there I think we could get a better, first class API. It could look like this

function TestForm() {
    // ... 
    const formApi = useFormApiRef();
    return (
        <div>
            <Form
                apiRef={formApi}
                onSubmit={() => {/*...*/ }}
                render={() => <div />}
            />
            <button onClick={() => {
                formApi.reset();
            }}>outsider button</button>
        </div>
    );
}
  )

dawidcxx avatar Jul 03 '19 11:07 dawidcxx

I'll consider this. You're not the first to request it. However, until/if it's implemented, it's not too difficult to do it oneself...

function TestForm() {
  const formRef = React.useRef()
  return (
    <div>
      <Form onSubmit={onSubmit}>
        {({ handleSubmit, form }) => {
          formRef.current = form
          return (
            <form onSubmit={handleSubmit}> ... fields ... </form>
          )
        }}
      </Form>
      <button onClick={() => formRef.current.reset()}>Reset</button>
    </div>
  )
}

erikras avatar Jul 09 '19 11:07 erikras

Not that I need it right now, but I remember using the proposed work around in my code in the past. This doesnt look good, but gets the job done. So I would be in favour of adding DI possibility for formApi.

Andarist avatar Jul 11 '19 20:07 Andarist

Another possibility is that there's a recent API change #520 (that I just now remembered to document 😅) that lets you provide your own form instance to <Form>, so something like this could work:

import { createForm } from 'final-form'

function TestForm() {
  const formRef = React.useRef(createForm({
    onSubmit: myOnSubmit
  })
  return (
    <div>
      <Form form={formRef.current}>
        {({ handleSubmit, form }) => (
          <form onSubmit={handleSubmit}> ... fields ... </form>
        )}
      </Form>
      <button onClick={() => formRef.current.reset()}>Reset</button>
    </div>
  )
}

erikras avatar Jul 12 '19 13:07 erikras

Exactly the kind of an API I had in mind 👌

Andarist avatar Jul 12 '19 14:07 Andarist

How can we use this in a class component?

Another possibility is that there's a recent API change #520 (that I just now remembered to document 😅) that lets you provide your own form instance to <Form>, so something like this could work:

import { createForm } from 'final-form'

function TestForm() {
  const formRef = React.useRef(createForm({
    onSubmit: myOnSubmit
  })
  return (
    <div>
      <Form form={formRef.current}>
        {({ handleSubmit, form }) => (
          <form onSubmit={handleSubmit}> ... fields ... </form>
        )}
      </Form>
      <button onClick={() => formRef.current.reset()}>Reset</button>
    </div>
  )
}

ayan-b avatar Feb 28 '23 10:02 ayan-b