Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form is refreshing after submit #1270

Closed
vblazenka opened this issue Jul 3, 2016 · 53 comments
Closed

Form is refreshing after submit #1270

vblazenka opened this issue Jul 3, 2016 · 53 comments

Comments

@vblazenka
Copy link

vblazenka commented Jul 3, 2016

Hi, I have a simple stateless form component and after I click Login button my page is refreshed.

How can I prevent my page from refreshing?

I use redux form 6 rc1

import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';

const validate = values => {
  const errors = {};

  if (!values.email) {
     errors.email = 'Required'
   } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
     errors.email = 'Invalid email address'
   }

   return errors;
}

const LoginForm = (props) => {
  const { handleSubmit } = props;
  return(
    <form onSubmit={handleSubmit}>
      <div>
        <label>E-mail</label>
        <Field name="email" component="input" type="text" />
        <button type="submit" className="button button--green">Login</button>
      </div>
    </form>
  );
}

export default reduxForm({
  form: 'login',
  validate
})(LoginForm);

@NeXTs
Copy link
Contributor

NeXTs commented Jul 4, 2016

same here

@NeXTs
Copy link
Contributor

NeXTs commented Jul 4, 2016

@wedranb Do you receive form values in handleSubmit?

I got a lot of weird getters and setters instead of values. What is even more interesting is that looks like arguments are mutating, because pay attention to object "preview" on top, it's differs from what we see after revealing this object in console
untitled-2

@vblazenka
Copy link
Author

@NeXTs I get the same thing.

@NeXTs
Copy link
Contributor

NeXTs commented Jul 4, 2016

Then you could temporarily use values.preventDefault() at least to prevent page refreshing
but I still can not handle this issue with values, that's madness

@erikras
Copy link
Member

erikras commented Jul 4, 2016

That is very bizarre. I'm not seeing that at all. For example, the submit validation example doesn't exhibit this behavior. handleSubmit really should be doing the preventDefault() for you.

You don't see this if you go back to 6a15?

@NeXTs
Copy link
Contributor

NeXTs commented Jul 4, 2016

Sure, I've tried many various releases, neither 6a15 or 6a6 helps
I've tried react-hot-loader v1, then v3, then come back to v1

I managed my dependencies to be exactly like in your example, but without luck

I have a hunch that this is due to the react-router or redux-auth-wrapper, checking right now

@NeXTs
Copy link
Contributor

NeXTs commented Jul 4, 2016

@erikras Well, I'm tired
Somehow by playing with various releases I handled weird getters/setters in arguments, so there are always that object from 'preview' now.
capture

Please take a look at this example in your free time, I have no more ideas what could be wrong as for this moment.

npm i
npm start
visit: http://localhost:3000/example

there would be single input field and submit button by clicking which I got response that I attached as image.

component path
src/components/Example.js

@NeXTs
Copy link
Contributor

NeXTs commented Jul 5, 2016

Hm, looks like redux-form differs between that one in examples and published into npm or something

@erikras In theory if I set up redux-form@v6.0.0-rc1 material ui example on my local machine, then go to /examples/material-ui and do
npm uninstall redux-form -S
npm i redux-form@6.0.0-rc.1 -S
npm start

this should works seamlessly, as soon as plugin's sources expected to be same, right?
but it does not, I get various errors. first of all react-hot-reload suddenly became unhappy
2
after commenting whole if (module.hot) {...} block, I get next error
MaterialUiForm.js:68 Uncaught TypeError: Cannot read property 'label' of undefined
here -> here

and console.log of field argument in renderTextField shows this
default

@erikras
Copy link
Member

erikras commented Jul 5, 2016

@NeXTs The source code that is identical to the npm published lib is going to be under the specific tag for that version. https://github.com/erikras/redux-form/tree/v6.0.0-rc.1/ That goes for the examples as well.

I have already made changes to the examples in the v6 branch that will make it not work with the version published on npm.

@NeXTs
Copy link
Contributor

NeXTs commented Jul 5, 2016

ok nevermind, things became much better after updating react-hot-reload@3.0.0 from alpha to beta version.
@wedranb try npm i react-hot-reload@3.0.0-beta.2, this should help

@erikras erikras closed this as completed Jul 6, 2016
@goldo
Copy link

goldo commented Aug 13, 2016

I'm having the same page reload problem after submitting with "redux-form": "6.0.0-rc.4"
Is it normal we have to trigger event.preventDefault() manually ?
If i don't do this, I get a url which looks like this after the page reload:
/register?username=Jon&email=Jon%40do.com&age=42

@NeXTs
Copy link
Contributor

NeXTs commented Aug 13, 2016

I suppose you have also incorrectly use onSubmit function.
you should pass your submit function from parent component to form component named exactly onSubmit={this.yourOnSubmitFunc}, but inside form component you should do onSubmit={this.props.handleSubmit}

so that your submit function wrapped in redux-form's submit function which prevents form submittion and does all other necessary job

@goldo
Copy link

goldo commented Aug 13, 2016

Thanks a lot 👍 I clearly missed that part in the documentation

@NeXTs
Copy link
Contributor

NeXTs commented Aug 13, 2016

You're welcome!
If you'd only knew how much time I spent on it... :D

@lakesare
Copy link

lakesare commented Aug 19, 2016

I had the same issue with my page refreshing on form submit.
That was caused by me passing handleSubmit instead of onSubmit in mapDispatchToProps. It was not very clear from docs for me that it would be the case.

@aspdev91
Copy link

aspdev91 commented Sep 5, 2016

I still can't resolve the issue. I don't understand solution too well since I'm new to React. Can someone provide their code or a deeper explaination? Thanks!

@lakesare
Copy link

lakesare commented Sep 5, 2016

@aspdev91, https://github.com/lakesare/memcode/search?utf8=%E2%9C%93&q=onSubmit
so we pass onSubmit in props to our component, BUT use this.props.handleSubmit in our component to get what we passed.

@aspdev91
Copy link

aspdev91 commented Sep 5, 2016

Thank you, but I still can't quite resolve it.. It says onSubmit is undefined. I am not exporting the code to any other modules or using hot reloading etc. Thanks!

class Form extends Component {

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

  componentDidMount() {
    this.refs.name            // the Field
      .getRenderedComponent() // on Field, returns ReduxFormMaterialUITextField
      .getRenderedComponent() // on ReduxFormMaterialUITextField, returns TextField
      .focus()                // on TextField
  }

  render() {
    const { handleSubmit, pristine, reset, submitting } = this.props
    return (
      <div className="container">
        <div className="Absolute-Center is-Responsive">
          <form  onSubmit={this.props.handleSubmit}>
            <div>
              <Field
                name="notes"
                component={TextField}
                hintText="Type anything"
                floatingLabelText="Type anything"
                multiLine={true}
                rows={4}/>
            </div>
            <div>
              <button type="submit" >Submit</button>
              <button type="button" onClick={reset}>Clear</button>
            </div>
          </form>
        </div>
      </div>
    )
  }
}

export default reduxForm({
  form: 'example',
},null,{ onSubmit})(Form)`

@NeXTs
Copy link
Contributor

NeXTs commented Sep 5, 2016

not somewhere but in parent's component where you define this Form, like

<Form onSubmit={() => console.log('yaa')} />

p.s. and yes, while defining Form you specify onSubmit but in Form component you use props called handleSubmit, this is not typo, this is intentional behaviour. I suppose explanation is here

@AndreasHoermandinger
Copy link

I get the same problems (refreshing, if I don't manually call preventDefault and some weird object instead of the formdata).
I'm using react@15.3.1, redux@3.6.0, redux-form@6.1.1 and for hot-reloading babel-preset-react-hmre@1.1.1 and webpack-hot-middleware@2.12.2 (webpack 2.1.0-beta.22)
the object I get instead of the data contained in the Form looks flatly like this
Proxy {dispatchConfig: Object, _targetInst: ReactDOMComponent, nativeEvent: Event, type: "submit", target: form.entireForm__app-components-FileUploadFrame-styles__dzso_…}
and has a lot of getters/setters inside

For submitting I do

<form className={styles.entireForm} onSubmit={handleSubmit}>
....
  <button className={styles.submitButton} type="submit">Submit</button>
</form>

Thank you in advance for any help/advice

@NeXTs
Copy link
Contributor

NeXTs commented Oct 25, 2016

@AndreasHoermandinger pay attention to #1270 (comment)

@AndreasHoermandinger
Copy link

@NeXTs I got

  render() {
    const { handleSubmit } = this.props;

Is this the problem? (in the examples only functions are used, I am using a class)
where handleSubmit is passed to props from the parent, still happens. I circumvented this by preventDefault and selecting the fields, but according to what's written in the docs that should not happen

@kellyrmilligan
Copy link

@NeXTs I am still seeing this issue on latest redux form in ie11.

parent component has

<LoginForm onSubmit={this.handleSubmit} />

and form component has

const LoginForm = (props) => {
  const { handleSubmit, submitting, error } = props
  return (
    <form onSubmit={handleSubmit} className="Login-Form">

@NeXTs
Copy link
Contributor

NeXTs commented Nov 4, 2016

@kellyrmilligan at ie11 only?

@kellyrmilligan
Copy link

yep, as far as I can tell. I haven't had a good chance to look, but where is it calling prevent default on the submit event?

@kellyrmilligan
Copy link

I see where it is doing this now. will check to see if the event is different in IE11 for some reason.

@kellyrmilligan
Copy link

it looks like nothing is actually working in ie11, this is on browserstack anyway. no validations are running, etc.

@blainegarrett
Copy link

blainegarrett commented Nov 11, 2016

I was struggling with this issue as well but really reading #1270 (comment) helped me out.

It appears reduxForm takes your passed onSubmit prop, wraps it and injects it into the wrapped form component as handleSubmit. See: https://github.com/erikras/redux-form/blob/master/src/reduxForm.js#L319

Gotchas:

  • onSubmit is also still passed as a prop it seems. If you use that as your handler to the form tag, then you are passed the dom event to the handler func instead of the map of form values.
  • If you pass the handler using a prop names handleSubmit (instead of onSubmit) then handler appears to be called with the event similar to the above.
  • If you leave off both onSubmit and handleSubmit from your form, the submission with correctly throw "reduxForm.js:125 Uncaught Error: You must either pass handleSubmit() an onSubmit function or pass onSubmit as a prop(…)"

Quick breakdown of the goods and bads for clarity:

<SampleForm onSubmit={showResults} /> // Good
<SampleForm whatever={showResults} /> // correctly throws error for missing expected prop
<SampleForm handleSubmit={showResults} /> // Bad under normal assumptions.  Won't error, your code gets run but with arg of dom event, form causes the page reload. Sadness ensues.

Breakdown of inside SampleForm class:

<form onSubmit={props.handleSubmit}>  // Good assuming handleSubmit wasn't directly passed in mistakenly. Arg to props.handleSubmit (ie the wrapped showResults) is form data not the dom event.
<form onSubmit={props.onSubmit}> // Bad, but won't error, form causes the page reload. The showResults code gets run, but with dom event as arg rather than the form data.

Hopefully that breakdown saves some headscratching for people coming here from google searches.

@kellyrmilligan
Copy link

Has anyone been able to see if ie11 is working? My form works everywhere but there

@yattias
Copy link

yattias commented Nov 12, 2016

I could not get this to work. Ended up using event.preventDefault() in my mapDispatchToProps

@yattias
Copy link

yattias commented Nov 13, 2016

I believe the main reason for the confusion here is that redux-form actually injects handleSubmit via a prop. You do not need to pass it in as a prop - if you do, you will overwrite redux-form's function.

Instead, you only need to pass in an onSubmit prop which will automatically get called by redux-form after validation is successful with the form values. If you do not have validation then your onSubmit function will be called immediately. I'll admit that this is pretty confusion.

const MyForm = (props) => {
  const { handleSubmit, onSubmit } = props; // Notice two functions, not one! Only onSubmit is passed in by you as a prop. The other is passed in by redux-form

  return (
    <form onSubmit={handleSubmit(onSubmit) }>
      <Field component="input" type="text" name="body" />
      <button type="submit">Submit</button>
    </form>
  )
}

Then you would use it like this (note how I am not passing in handleSubmit):

<MyForm onSubmit={someFunctionThatWillHandleFormValues}/> 

Here is a reference to an article that made me realize that. Check out the code sample.

@kellyrmilligan
Copy link

just got back to testing this out again. can't pin down what change made the fix, but in between 6.1.1 and 6.2, ie11 was throwing an error in 6.1.1 const must be initialized, and it was in a for loop that was a polyfill for object.assign. it was for (const key in source), and now it's for (var key in source). so whatever you did, thanks!

I can now actually use this library :)

in the compiled reduxForm.js, it's line 13. this seems like a change in babel pherhaps? or corejs?

@mschipperheyn
Copy link

mschipperheyn commented Dec 1, 2016

#1270 (comment) solved it for me. I moved the submit function out of the form class into the parent class and supplied it as onSubmit property, although I find it very counter intuitive that this is necessary. You should be able to do the same thing within the form class itself. But this leads to the page refreshing (even on submit failure)

@ThadeuLuz
Copy link

Please, don't pass onSubmit prop through. Rename that if you need it, but make it undefined on the form component. It makes sense when you get it but until you do, there goes your evening..

Better yet, replace it with something like

onSubmit() {
  alert('Do NOT use <form onSubmit={props.onSubmit}>, if you do you'll get cancer! Use <form onSubmit={props.handleSubmit}> instead');
}

@mcverter
Copy link

mcverter commented Feb 5, 2017

This had me stumped for a while. I finally resolved it by passing the default handleSubmit prop my own handleSubmitForm function

=========================================================

import React, {Component} from 'react';
import {Field, reduxForm} from 'redux-form';

class MyForm extends Component {
  constructor(props) {
    super(props);
    this.handleMyFormSubmit = this.handleMyFormSubmit.bind(this);
  }

  handleMyFormSubmit({val1, val2}) {
    console.log("Form values", val1, val2;
  }

  render () {
    const {handleSubmit} = this.props;
    return (
      <form onSubmit={handleSubmit(this.handleMyFormSubmit}>
        <Field name="val1" type="text" component="input" label="Value 1l"/>
        <Field name="val2" type="password" component="input" label="Value 2"/>
        <div>
          <button type="submit">Submit</button>
        </div>
      </form>
    );
  }
}
export default   reduxForm({
    form: 'myForm',
    destroyOnUnmount: false,        // <------ preserve form data
    forceUnregisterOnUnmount: true,  // <------ unregister fields on unmount
    validate
  })(Signin);

@matt-way
Copy link

This is an extremely confusing problem, and required quite a few re-reads through the comments above. This should definitely be rethought, refactored, or at least have updated documentation that clarifies this problem. If anyone gets to the end here and still doesn't understand I'll try another explanation.

If you were like me, then your first thought from reading the docs might be to try:

someFuncInsideComponent(values) {
  console.log('got the values')
}

render() {
  return (
    <form onSubmit={this.someFuncInsideComponent}>
    ...

This will cause the refresh problem. That is because you are not supposed to put your function inside onSubmit. You need to write <form onSubmit={handleSubmit}> and only that. This is because redux-forms injects the handleSubmit function, and has nothing to do with your code.

In order to run a function with the form results, it needs to sit outside the component where you declare <form>. It also needs to be passed in as onSubmit={yourOuterFunc}. It might look something like:

someFunction(values) {
  console.log('got the values')
}

render() {
  return (
    <MyCustomForm onSubmit={this.someFunction}/>
  )
}

Where inside MyCustomForm you have declared the line above <form onSubmit={handleSubmit}>.

The confusing bit is that both the inner and outer function must both use onSubmit, but the inner one needs to be written a specific way. I feel like the examples above where they explicitly call handleSubmit inside their form control makes a lot more sense when read, and lets you handle the values inside your form control, and not be forced to use a parent function.

@betoharres
Copy link

I had the same issue, wasted some hours trying to figure out, I think it should have more visible since you have to do EXACTLY like @NeXTs said

@sobeslavsky
Copy link

I also needed to declare onSubmit function in my form class and found the solution of @mcverter working fine. As this is what most people here are looking for I believe this should be the recommended solution.

@Stas-Buzunko
Copy link

why the hell #1270 (comment) is not in docs?
spent a few hours on this

@mikemerritt
Copy link

I agree with @Stas-Buzunko. It should be made clear in the docs that the handler needs to be passed in from outside the form component. I had assumed that this functioned the way most other components do and I could just pass this.handlerFunction() to onSubmit.

@chillenious
Copy link

+1 for making this clear in the docs and examples, I also spent an hour or so on it :-)

@gustavohenke
Copy link
Collaborator

PRs are welcome.

@Razzwan
Copy link

Razzwan commented Apr 3, 2017

+1 for marking this clear in the docs. I expected this to work exactly like all other components. I lost the whole day solving this problem. Oh...

ps: If I were a little stupider, and just copied an example from the documentation, this would not happen. Or vice versa?

@ghost
Copy link

ghost commented May 7, 2017

Had the similar issue with onSubmit and handleSubmit.

component:

render() {
    const { handleSubmit, onSubmit } = this.props;
    return (<form onSubmit={handleSubmit(onSubmit)}>...</form>);
}

container

import { bindActionCreators } from 'redux';
import { reduxForm } from 'redux-form';
import { connect } from 'react-redux';

const mapDispatchToProps = dispatch =>
  bindActionCreators({
    onSubmit: submitForm,
  }, dispatch);

export default connect(undefined, mapDispatchToProps)(reduxForm({
  form: 'formName',
})(MyComponent));

action creator

import { formActionType } from '../constants/actionTypes'; //  'SUBMIT_FORM'

export const submitForm = values => ({
  type: formActionType.SUBMIT_FORM,
  payload: values,
});

Hope that the example I've provided can help someone to save some time.
My question is how this part handleSubmit(onSubmit) can be improved in my code. Thanks!

@zacacollier
Copy link
Contributor

zacacollier commented May 8, 2017

@gustavohenke if I were to submit a PR, would you say that FAQs are the most appropriate section for this common problem?

EDIT: never mind - looking at the faqs, I see now that there's already a relevant entry.

zacacollier added a commit to zacacollier/redux-form that referenced this issue May 9, 2017
Elaborated on the `onSubmit` vs. `handleSubmit` FAQ in an attempt to address some of the confusion witnessed in redux-form#1270.
erikras pushed a commit that referenced this issue May 9, 2017
Elaborated on the `onSubmit` vs. `handleSubmit` FAQ in an attempt to address some of the confusion witnessed in #1270.
yih-en added a commit to GovWizely/zAPIness-search-widget that referenced this issue May 19, 2017
Form will be refreshed if users press enter. This is not desirable because the search should be performed while users are typing.
Refer to redux-form/redux-form#1270, handleSubmit supposes to do e.preventDefault() to preview form from submitting.
Also, refer to redux-form/redux-form#190, we need to pass onSubmit as props to the form
@tushar-borole
Copy link

use e.preventDefault()

@habilit
Copy link

habilit commented Feb 13, 2018

I haved faced the same problem and that's my fault to inject wrong name in Redux form.
Thank you :) :)

@mandajoan
Copy link

mandajoan commented Feb 15, 2018

I solved this issue by throwing a 'Submission Error' in my action creator. Because my API would send a status '200' when there was an issue with the user's login input, the form would submit and then refresh with the user's input gone because my authentication would kick it back.

The example and documentation for Submission Error from the Redux-Form api is here.

I went ahead an put it in my action creator in the second ' .then ' statement I set up.

.then(response => {
  if (the input is valid) {
                    dispatch(loginSuccess())
 
                } else {
                   dispatch(renderErrorMessage(however you pass the error message from the response))
                    throw new SubmissionError(login_response.error_message) <--stops the form from submitting and allow me to display my error message

}
}

This I bound my form handler to the handleSubmit:

 <form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>

I had no issues with my data not being accessible in my action creator/in the component.

@arturtr
Copy link

arturtr commented Dec 7, 2018

It should be placed on the first page of documentation with bold and other attention marks

!!! IMPORTANT !!!
You need to pass onSubmit prop to the form component, but read handleSubmit inside of it. handleSubmit magically wrap onSubmit by reduxForm HOC

Because already 4+ years this issue happen with many people

@dsldiesel
Copy link

Guys, another one here spending hours in this.
For the sake of simplicity, flexibility, modularity, and good practices, I just WANNA declare the submit handler INSIDE the child form component, and not pass it as a prop from the parent component.
Well, as you see, no way to do it.
This is not good coding.
The parent is a main app component that will be abstracted to include, then, different child components with different functionalities as needed, and has nothing to do with form onsubmit handlers.
This leads to non-semantic code.

@iamandrewluca
Copy link
Member

iamandrewluca commented Sep 24, 2019

@dsldiesel

<form onSubmit={props.handleSubmit(formData => {
  // this is your submit function
})}>
  {/* form contents */}
</form>

@dsldiesel
Copy link

@iamandrewluca Thanks!
Interesting, this is a workaround.
I'd sware this is not known by other coders above who complaint as I did :)

@iamandrewluca
Copy link
Member

@dsldiesel This is not a workaround 🙂
https://redux-form.com/8.2.2/docs/api/props.md/#-code-handlesubmit-eventorsubmit-function-code-

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests