Git Product home page Git Product logo

Comments (50)

Aeon-Avinash avatar Aeon-Avinash commented on May 12, 2024 26

Works perfectly with async/await

onSubmit={async event => {
              await handleSubmit(event)
              form.reset()
            }}

I tried various suggestions to reset the form on successful submission but to no avail. I was just about to give up on Final Form and move back to Formik.

But then I tried my luck with async/await and it works like a charm!
Thanks Final Form 🥇

from react-final-form.

michalmodrzejewski avatar michalmodrzejewski commented on May 12, 2024 25

Final-form introduced new type in 4.20 version
https://final-form.org/docs/final-form/types/FormApi

Quote from docs:
"restart
() => void
Resets all form and field state. Same as calling reset() on the form and resetFieldState() for each field. Form should be just as it was when it was first created."

Example code:
const onSumbit = form => setTimeout(() => form.restart())
or with destructuring
const onSumbit = { restart } => setTimeout(() => restart())

from react-final-form.

erikras avatar erikras commented on May 12, 2024 18

Once the fix in #32 is released, the answer is:

<Form
  onSubmit={onSubmit}
  initialValues={{ employed: true }}
  render={({ handleSubmit, reset }) => (
    <form
      onSubmit={event => {
        handleSubmit(event).then(() => {
          reset() // or could be passed directly to then()
        })
      }}
    >
    ...
    </form>
  }/>

from react-final-form.

tomkis avatar tomkis commented on May 12, 2024 12

Not sure if i am doing something wrong.

However - form.reset used as described above indeed resets its values but does not reset field state. Which results in validation errors after the submission.

So what I have to do is to reset each individual field state manually like:

              handleSubmit(ev)?.then(() => {
                form.reset();
                form.resetFieldState("amount");
                form.resetFieldState("ingredient");
              });

So either I am missing some prop (which I don't seem to see in docs) which would reset not only values but also whole field state or form.reset does not work as one would expect.

from react-final-form.

stunaz avatar stunaz commented on May 12, 2024 11

@erikras wouldn't be best to pass the reset or maybe others helpers to onSubmit.

the signature would be like :
onSubmit: (values: Object, callback: ?(errors: ?Object) => void, reset: Function, ....) => ?Object | Promise<?

from react-final-form.

golestanirad avatar golestanirad commented on May 12, 2024 10

when i use

 <Form
      onSubmit={values => {
        console.log("values, ", values)
      }}
      render={({ handleSubmit, form }) => (
        <form
          onSubmit={async event => {
            await handleSubmit(event)
            form.reset()
          }}
        >

because of that

form.reset()

my errors for validation are not shown.

from react-final-form.

scorchiowned avatar scorchiowned commented on May 12, 2024 9

Not sure if the best way to proceed with this but you can set a ref on the form instance and on your onSubmit callback fn access the forms reset prop as such

onSubmit = values => {
	this.refs["user-form"].form.reset()
};

from react-final-form.

apiwonska avatar apiwonska commented on May 12, 2024 7

I wanted my form to reset fields after form is successfully submitted. This is the solution working in my case:

<Form onSubmit={this.onSubmit}>
  {({handleSubmit, form, submitSucceeded, values}) => {
    if (submitSucceeded) {
      form.reset();
      Object.keys(values).forEach(field => form.resetFieldState(field));
    }
    return (
    < form onSubmit = {handleSubmit} >
      ...
    </ form>
    )
  }}
</Form>

It's a pitty form.reset() does not automatically turn fields touched property to false, which for my form results showing validation errors (fields are required).

from react-final-form.

Akirtovskis avatar Akirtovskis commented on May 12, 2024 6

EDIT: solved by just putting form.reset() in my handleSubmit method

I have form where I am not accessing event at all and I have problem resetting form after it has been submitted.

I did try this, but form gets reset before it is submitted. As for validation - errors show up, but after that form resets anyway.

onSubmit={() => {
           handleSubmit(values).then(reset);
         }}

I also tried other aforementioned options, but without any success.

Here is the relevant code from my form :

handleSubmit(values) {
console.log(values.firstName);

//Setting up values for fetch body
let firstName = values.firstName;
let email = values.email;
let subject = values.subject;
let message = values.message;

fetch('/contact/send', {
  method:'POST',
  headers:{
    'Accept':'application/json, text/plain, */*',
    'Content-Type':'application/json'
  },
  body:JSON.stringify({
    firstName:firstName,
    email:email,
    subject:subject,
    message:message,
  }),
})
.then(res=>res.json())
.then(console.log('here'))
.then(data=>console.log(data))
.catch(err=>console.log(err));
};

render() {
  return (
    <div className="contact">
      <div className="contact__form">
        <Form
    onSubmit={this.handleSubmit}
    validate={values => {
      const errors = {};
      if (!values.firstName) {
        errors.firstName = "Required";
      }
      if (!values.subject) {
        errors.subject = "Required";
      }
      if (!values.email) {
        errors.email = "Required";
      } else if(!values.email.match( /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)) {
        errors.email = "Please enter a valid e-mail adress"
      }
      if (!values.message) {
        errors.message = "Required";
      }
      return errors;
    }}
    render={({ handleSubmit, submitting, values, reset}) => (
      <form
        onSubmit={handleSubmit}
      >
        <Field name="firstName">
          {({ input, meta }) => (
            <div>
              <input {...input}
                type="text"
                placeholder="Name"
              />
              {meta.error && meta.touched && <span>{meta.error}</span>}
            </div>
          )}
        </Field>
       ....REST OF THE FIELDS 

from react-final-form.

erikras avatar erikras commented on May 12, 2024 5

Fix published in v1.1.1.

from react-final-form.

Soundvessel avatar Soundvessel commented on May 12, 2024 5

We really could use a handler to clear the contents of the form but does not affect form states like submitSucceeded which are often used to display a success message.

from react-final-form.

avbee avatar avbee commented on May 12, 2024 5

Regarding @golestanirad post on validation errors not showing - I had the same problem and it took me a while to find the solution. I think it's not because of form.reset(). In my case, when I had validation errors, async handleSubmit was not executed at all and returned undefined, then form reset was executed. What worked for me was checking if handleSubmit is undefined or returns empty object before resetting the form.

from react-final-form.

leonardyrj avatar leonardyrj commented on May 12, 2024 5

Funcionou dessa forma
const onSumbit = (value,form) => { console.log(values) setTimeout(form.reset) }

from react-final-form.

bertho-zero avatar bertho-zero commented on May 12, 2024 5

There is no more need to do this kind of workaround, I made a PR that allows the reset during the submission: https://github.com/final-form/final-form/pull/363/files#diff-582693474d2a90e13161b9d64da11dd53a1e4a811df74d614d87463fffa1c8d7

You can now simply do:

const onSubmit = (values, form) => {
  // what do you want
  form.reset();
}

from react-final-form.

davidhenley avatar davidhenley commented on May 12, 2024 4

This is still not working for me on latest version.

<Form
    onSubmit={values => {
      return new Promise((res, rej) => {
        axios.post('/api/forms/creditdebit', values)
          .then(response => res())
          .catch(error => res({ error }));
      })
    }}
    validate={validate}
    component={CreditDebitForm}
/>
<Form onSubmit={event => {
      handleSubmit(event).then(() => {
        reset()
      })
    }}>

I get: TypeError: Cannot read property 'then' of undefined. Tried using async too with no luck. It submits, so it is calling.

from react-final-form.

hdrdavies avatar hdrdavies commented on May 12, 2024 4

@NYCJacob Make sure your code looks something like this (following @Aeon-Avinash's example). It's working for me:

    <Form
      onSubmit={values => {
        console.log("values, ", values)
      }}
      render={({ handleSubmit, form }) => (
        <form
          onSubmit={async event => {
            await handleSubmit(event)
            form.reset()
          }}
        >

from react-final-form.

douglasjunior avatar douglasjunior commented on May 12, 2024 4

I have the same problem of the @tomkis.

When call setTimeout(form.reset) the global form state is cleared, but the fields states stay with touched and others properties preserved.

A very ugly solution is to call form.resetFieldState for all fields.

    const onSubmit = useCallback(async (values, form) => {
        try {
            await axios.post(...);

            setTimeout(() => {
                Object.keys(values).forEach(key => {
                    form.resetFieldState(key);
                });
                form.reset();
            });
        } catch (err) {
            ...
        }
    }, []);

    return (
        <Form
            onSubmit={onSubmit}
            render={...}
        />
    );

from react-final-form.

davidhenley avatar davidhenley commented on May 12, 2024 3

Spoke too soon. Still not working. Cannot read property 'then' of undefined. @erikras

const onSubmit = (values, user) => {
  return new Promise(resolve => {
    axios.post('/api/forms/samples', { values })
      .then(response => resolve())
      .catch(error => resolve({ error }));
  });
}

const FormContainer = ({ user }) => {
  return (
    <Form
      onSubmit={(values) => onSubmit(values, user)}
      mutators={{
        ...arrayMutators
      }}
      initialValues={{ products: [{ placeholder: null }] }}
      validate={validate}
      component={SamplesForm}
    />
  );
}
<form onSubmit={event => {
      handleSubmit(event).then(() => reset())
    }}>

from react-final-form.

soroushchehresa avatar soroushchehresa commented on May 12, 2024 3

I'm not sure this code is the best way but it's working for me:

import React from 'react';
import { Form } from 'react-final-form';

const Component = () => {
  let handleResetForm = null;

  const handleSubmitForm = () => {
    // Do something...
    handleResetForm();
  };

  return (
    <Form
      onSubmit={handleSubmitForm}
      render={({ handleSubmit, pristine }) => {

        // Referenced the reset method to out of the form
        if (!handleResetForm && form && form.reset) {
	  handleResetForm = form.reset;
        }

        return  <form onSubmit={handleSubmitForm}> ... </form>;
      }}
    />
  );
}

"final-form": "^4.18.5"
"react-final-form": "^6.3.0"

from react-final-form.

martinnov92 avatar martinnov92 commented on May 12, 2024 3

I do it this way:

const [formKey, setFormKey] = useState(Date.now());
...
<Form
  key={formKey}
  ...
  onSubmit={() => {
    // save to server
   setFormKey(Date.now());
  }}
/>

from react-final-form.

wontheone1 avatar wontheone1 commented on May 12, 2024 3

Here's a working sandbox with my suggestion from above.

Edit 🏁 React Final Form - Reset After Submit

Doesn't seem to work with final-form 4.20.1 and react-final-form 6.5.1. @erikras
Solved it using the second argument of onSubmit function which is the form.

const onSubmit = async (values, form) => {
    handleCalculate();
    setTimeout(() => form.initialize({}), 10);
    form.resetFieldState("amount_known");
    form.resetFieldState("used_electricity_amount");
  }

<Form
      onSubmit={onSubmit}

or form.restart() seems to reset all the fields too.

Another way that works is using form.reset() in the render prop of Form

    <Form
      onSubmit={onSubmit}
      render={({ handleSubmit, values, form }) => (
        < form
          className='form'
          id='real-estate-form-2'
          onSubmit={event => handleSubmit(event).then(() => {
            form.reset();
          })}>

from react-final-form.

kalutheo avatar kalutheo commented on May 12, 2024 2

Hi @davidhenley i managed to make it work see this example :

https://stackblitz.com/edit/react-final-form-reset-submit?file=index.js

from react-final-form.

klis87 avatar klis87 commented on May 12, 2024 2

@stunaz I completely agree. Especially we already have callback, which de facto is just setSubmitError action, so why not to add other actions, like reset.

@erikras the problem with your promise solution is, that this is not always possible. For instance, when you use redux-saga instead of redux-thunk, you wont have promise at your disposal, so it is necessary to have a reset in onSubmit itself, so it could be passed to saga there for a later execution.

from react-final-form.

ronn avatar ronn commented on May 12, 2024 2

Solved putting form.reset() in the parent component

from react-final-form.

VincentCharpentier avatar VincentCharpentier commented on May 12, 2024 2

@soroushchehresa quick notes:

  • you are reassigning a const variable.
  • you should add form in the render prop function

This should be enough:

<form onSubmit={handleSubmit.then(form.reset)}>

from react-final-form.

srdjanblagojevic avatar srdjanblagojevic commented on May 12, 2024 2

I think that this is the best practice.

final-form handleSubmit method has 3 parameters, values, form and callback.
You need to point which method will be called on callback,, and you can add form.reset for that.
In this sample, I'm collecting only edited values, and sending them to my handleFormSubmit async method.

<Form
	validate={validateFields}
	onSubmit={(values, form, callback) => {
		// eslint-disable-next-line no-param-reassign
		callback = form.reset;
		const changedValues = {};
		Object.keys(form.getState().dirtyFields).forEach(propName => {
			changedValues[propName] = values[propName]
		});
		return handleFormSubmit(changedValues);
	}}

from react-final-form.

vijaychouhan-rails avatar vijaychouhan-rails commented on May 12, 2024 2

Ref

const handleSubmitForm = (values, action) => {
    console.log("Form values", values)
    CALL_AN_API.then((res) => {
      action.resetForm(); // Reset the form to initialValues
    })
  };

<Formik
  initialValues={initialValues}
  onSubmit={handleSubmitForm}
  validationSchema={validationSchema}
  enableReinitialize
>
....
</Formik>

from react-final-form.

NYCJacob avatar NYCJacob commented on May 12, 2024 1

@hdrdavies I get the form to reset, but that just clears the form. I would like to display some kind of success/failure message. I am afraid to try converting the form to a class and use state because final-form is doing so much internally. I was looking at the response object on return but I still need state I think to conditionally render a message.

from react-final-form.

VincentCharpentier avatar VincentCharpentier commented on May 12, 2024 1

@golestanirad you don't have a form variable so you're calling reset() on undefined variable, that must be your issue.
If your destructure form in render property, then also extract reset function and call it directly:
#21 (comment)

from react-final-form.

VincentCharpentier avatar VincentCharpentier commented on May 12, 2024 1

Ah ok. Then I would suggest something like this:

<form 
  onSubmit={
    async (...args) => {
      await handleSubmit(...args);
      form.reset();
    }
  }>

from react-final-form.

bertho-zero avatar bertho-zero commented on May 12, 2024 1

Remember that your onSubmit function not only receives values, but also the form object:

function MyComponent() {
  const mySubmit = useCallback(
    (values, form) => {
      // Do what you want with your values...

      setTimeout(form.restart); // or setTimeout(form.reset())
    },
    [/* ... */]
  );

  return (
    <Form
      onSubmit={mySubmit}
      component={MyForm}
    />
  );
}

cf. https://final-form.org/docs/react-final-form/types/FormProps#onsubmit

from react-final-form.

kalutheo avatar kalutheo commented on May 12, 2024

Hi @erikras thanks for the fix i will try on my side and upgrade to v1.1.1

from react-final-form.

davidhenley avatar davidhenley commented on May 12, 2024

Try it using component. It still doesn't work for me. This is my one pain with RFF right now. I'll try again tonight.

from react-final-form.

erikras avatar erikras commented on May 12, 2024

Here's a working sandbox with my suggestion from above.

Edit 🏁 React Final Form - Reset After Submit

from react-final-form.

davidhenley avatar davidhenley commented on May 12, 2024

Heads up, you cannot use handleSubmit(e).then(... unless you disable your submit on invalid. The middleman does not return a promise so there is no .then

from react-final-form.

stunaz avatar stunaz commented on May 12, 2024

opened an issue #69 to get more visibility

from react-final-form.

ronn avatar ronn commented on May 12, 2024

"Uncaught TypeError: Cannot read property 'then' of undefined at onSubmit"
:/

from react-final-form.

shanebeehler avatar shanebeehler commented on May 12, 2024

Make sure you add return in front of fetch/axios or whatever library you're using to make POST request.

return fetch('/', { method: 'POST'......

from react-final-form.

NYCJacob avatar NYCJacob commented on May 12, 2024

any examples showing a submit success message to the user by rendering a component rather that an alert window or would that require make a class out of the form

from react-final-form.

khaoptimist97 avatar khaoptimist97 commented on May 12, 2024

As for using reset in onChange() of something inside the form? Anyone have an idea. Please suggest me

from react-final-form.

doxomo avatar doxomo commented on May 12, 2024

@ronn

onSubmit={(event) => {
  const promise = handleSubmit(event);
  console.log('heyyy :-D', promise);
  promise && promise.then(() => {
    reset();
  })
  return promise;
}}

from react-final-form.

NYCJacob avatar NYCJacob commented on May 12, 2024

@Aeon-Avinash this still doesn't work for me :(

from react-final-form.

VincentCharpentier avatar VincentCharpentier commented on May 12, 2024

@tomkis

  1. you code will only reset if you handleSubmit is async or excplicitly return a promise (to execute the "?.then" callback)
  2. What part of field state are you talking about ?
    because once the reset is done your validation function get the initialValues, which can be valid or not depending on your validation function

from react-final-form.

tomkis avatar tomkis commented on May 12, 2024

ad 1) yes I am well aware of that

ad 2) - i am talking about touched flag which remains true even after resetting the form - only resetFieldsState resets it back.

from react-final-form.

VincentCharpentier avatar VincentCharpentier commented on May 12, 2024

I'm seeing the same issue when I tried (here https://codesandbox.io/s/epic-platform-wtm5s)

Maybe you could use "dirtySinceLastSubmit" instead ?

from react-final-form.

soroushchehresa avatar soroushchehresa commented on May 12, 2024

@VincentCharpentier Thanks for the notes.
In my case, the handleSubmit method doesn't return a promise!

from react-final-form.

soroushchehresa avatar soroushchehresa commented on May 12, 2024

@VincentCharpentier My handleSubmit method doesn't return a promise,
So I can't use await or then. My suggested example is just for non-async flows, something like using forwarding refs!

Async Functions
Forwarding Refs

from react-final-form.

Soundvessel avatar Soundvessel commented on May 12, 2024

Wouldn't it make more sense to use form.initialize so you keep the submitSuccess state? You can pass an empty object or whatever you previous used for initial values. I think this also sets the form state of pristine to true again too so you can use that state with submitSuccess to determine the first submission vs second etc.

  const onSubmit = useCallback(
    async function onChangePasswordFormSubmit(values, form) {
      try {
        await updatePassword(values)
        // clears focus if submit via enter press
        document.activeElement.blur()
        // re-initialize form AFTER submitSuccess to prevent re-focus on first field
        setTimeout(() => form.initialize({}), 20) // resets form without losing submitSucceeded state
        return undefined // triggers submitSuccess state
      } catch (error) {
        console.error(error)
        return mapErrors(error)
      }
    },
    [ updatePassword]
  )

from react-final-form.

bertho-zero avatar bertho-zero commented on May 12, 2024

It depends on the need, everyone can do an initialize, a reset or a restart.

I don't really see the interest of the setTimeout and the return here.

from react-final-form.

fkunecke avatar fkunecke commented on May 12, 2024

@bertho-zero has the right idea, but I found that calling form.reset() clears the form, then runs validation. I found it's better to call form.restart() because it doesn't run validation. An example use case is a user opens up a dialog with a form, clicks a field, then closes the dialog. Because the field has been touched, validation may render an error.

Here's my handleSubmit:

const handleSubmit = async(data, form) => {
  setLoading(true);
  const result = await doWork(data);
  setLoading(false);
  handleClose(form);
}

...

const handleClose = (form) => {
  onClose();
  // if we've been passed a form, restart it to clear without validation
  form && form.restart && form.restart();
};

from react-final-form.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.