redux-form - onSubmit doesnt work - reactjs

I'm using redux-form and I just cant get the onSubmit fuction to work.
EDIT: My problem is that the function is not being called, i put debugger on the onSubmit and it doesnt get there.
here is my form:
class userForm extends Component {
onSubmit(values) { // do here something }
render() {
const { handleSubmit } = this.props;
return <form onSubmit={handleSubmit(this.onSubmit)}>
<Field name='id'
component={TextField}
label='id'/>
<Field name='name'
component={TextField}
label='name' />
<button type='submit'>Submit</button>
</form>
}
}
export default reduxForm({
form: 'userForm'
})(userForm);
But it never gets to the onSubmit method.
What am I doing wrong?

you just need to add .bind keyword after submit,
class userForm extends Component {
onSubmit(values) { // do here something }
render() {
const { handleSubmit } = this.props;
return <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<Field name='id'
component={TextField}
label='id'/>
<Field name='name'
component={TextField}
label='name' />
<button type='submit'>Submit</button>
</form>
}
}
export default reduxForm({
form: 'userForm'
})(userForm);

This is an edited version of the pattern I use.
Note the use of the bind keyword.
Generally I use redux to manage state, and would also use an action inside the function handleFormSubmit. But this should get you on the right track.
import React, { Component } from 'react';
import { reduxForm } from 'redux-form';
class Userform extends Component {
static handleFormSubmit({ id, name}) {
console.log({id, name});
}
render () {
const { handleSubmit, fields: { id, name }} = this.props;
return(
<form onSubmit={handleSubmit(Userform.handleFormSubmit.bind(this))}>
<fieldset>
<label>Id:</label>
<input {...id}/>
</fieldset>
<fieldset>
<label>Name:</label>
<input {...name} />
</fieldset>
<button action="submit">Submit</button>
</form>
);
}
}
export default reduxForm({
form: 'userform',
fields: ['id', 'name']
})(Userform);

Related

Transform Function Component -> Class Component

How to transform this function complement to class component
:
const SyncValidationForm = (props) => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form className ="formmailforbook" onSubmit={handleSubmit(submit)}>
<Field name="email" type="email" component={renderField} label="Email"/>
<div>
<button className ="hero_button margin_left" type="submit" disabled={submitting}>Submit</button>
</div>
</form>
)
}
Pretty easy translation, you can do the same prop destructuring in the render method. Only slight change is that now it's pulling from this.props:
import React, { Component } from 'react';
export default class SyncValidationForm extends Component {
render () {
const { handleSubmit, pristine, reset, submitting } = this.props;
return (
<form className ="formmailforbook" onSubmit={handleSubmit(submit)}>
<Field name="email" type="email" component={renderField} label="Email"/>
<div>
<button className ="hero_button margin_left" type="submit" disabled={submitting}>Submit</button>
</div>
</form>
)
}
}
It's pretty much easy.. copy the code to the new file and add export defaultbefore const something like this.
export default const SyncValidationForm
Import the file as you import other components where ever you want the component and use the imported name as jsx name as usal and provide props.

How to handleSubmit with a redux-form

I'm working to use redux-form for the first time. I am able to render the form but I have not been able to handle the submit. While I eventually want to send the data to the server, at this point, I'm simply trying to console log the form field values. I'm getting the error:
Error: You must either pass handleSubmit() an onSubmit function or pass onSubmit as a prop
Here's my Profile.jsx file
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {withAuth} from 'react-devise';
import { Field, reduxForm } from 'redux-form';
class Profile extends Component {
handleSubmit(data) {
console.log('Submission received!', data);
}
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text"/>
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" component="input" type="text"/>
</div>
<div>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email"/>
</div>
<button type="submit">Submit</button>
</form>
);
}
}
// Decorate the form component
Profile = reduxForm({
form: 'profile' // a unique name for this form
})(Profile);
const mapStateToProps = state => {
return {
currentUser: state.currentUser
};
};
export default connect(mapStateToProps)(withAuth(Profile));
How can I handle the submitted values in a way where I can eventually send them to my API?
Redux-Form decorates your component with handleSubmit prop. According to docs it's:
a function meant to be passed to <form onSubmit={handleSubmit}> or to
<button onClick={handleSubmit}>. It will run validation, both sync and
async, and, if the form is valid, it will call
this.props.onSubmit(data) with the contents of the form data.
Optionally, you may also pass your onSubmit function to handleSubmit
which will take the place of the onSubmit prop. For example:
So if your component doesn't have onSubmit property you have to 'manually' pass your submit handler to handleSubmit function. Please try this:
<form onSubmit={this.props.handleSubmit(this.handleSubmit.bind(this))}>
Please don't confuse your handleSubmit method with prop passed from Redux-Form with the same name.
(Posted solution on behalf of the question author to move it to the answer space).
Working code:
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {withAuth} from 'react-devise';
import { Field, reduxForm } from 'redux-form';
class Profile extends Component {
handleSubmit(data) {
console.log('Submission received!', data);
}
render() {
return (
<form onSubmit={this.props.handleSubmit(this.handleSubmit.bind(this))}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text"/>
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" component="input" type="text"/>
</div>
<div>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email"/>
</div>
<button type="submit">Submit</button>
</form>
);
}
}
// Decorate the form component
Profile = reduxForm({
form: 'profile' // a unique name for this form
})(Profile);
const mapStateToProps = state => {
return {
currentUser: state.currentUser
};
};
export default connect(mapStateToProps)(withAuth(Profile));

Redux-form onSubmit nothing happens

I would like to ask, what I miss on my code. It seems submitForm function is not working/triggering when I submit the form. I can't get values from my form fields. Here's my code:
import React from 'react';
import { reduxForm,reset, Field } from 'redux-form';
class FormProfile extends React.Component {
submitForm(formProps){
console.log(formProps);
}
render(){
const { error, handleSubmit } = this.props;
return (
<form onSubmit={this.submitForm.bind(this)}>
<Row>
<Col lg={6}>
<Field name="name" type="text" component={TextBoxComponent} placeholder="Compay Name" label="* Company Name" required />
<Field name="website" type="text" component={TextBoxComponent} placeholder="www.yourdomain.com" label="Website" />
<Field name="email" type="text" component={TextBoxComponent} placeholder="How can we contact your Company" label="* Contact Email" required />
</Col>
</Row>
</form>
);
}
}
const form = reduxForm({
form: 'CreateCompanyProfileForm',
validate
});
function validate(formProps){
const error = {};
return error;
}
export default (form(FormProfile));
TextBox Componen
import React from "react";
class TextBoxComponent extends React.Component {
render(){
return (
<div className="form-group">
<label className="control-label">{this.props.label}</label>
{ this.props.sublabel !== undefined ?
<em className="text-info"> { this.props.sublabel }</em>
:null}
<input { ...this.props } type={this.props.type} placeholder={this.props.placeholder} className="form-control"/>
{ this.props.required && <span className="text-error"></span> }
</div>
);
}
}
export default TextBoxComponent;
You should modify this line:
<form onSubmit={this.submitForm.bind(this)}>
to:
<form onSubmit={handleSubmit}>
then you can remove:
submitForm(formProps){
console.log(formProps);
}
Then you can create a new component to wrap redux form component:
class SamplePage extends React.Component {
handleSubmit = (values) => {
// Do something with the form values
console.log(values);
}
render() {
return (
<FormProfile onSubmit={this.handleSubmit} />
);
}
}
Anyway, you should check the example from Redux-form docs: http://redux-form.com/6.5.0/docs/GettingStarted.md/

redux-form v6: Form submission canceled because the form is not connected

I am getting this error in my console.
"Form submission canceled because the form is not connected"
after trying to migrate my redux-form from v5 to v6 since we migrated our app to a more recent version of React.
I am not sure what is going wrong here so i figured I could use a second or third pair of eyes.
Here is my "Smart Component"
import React, { PropTypes } from 'react';
import { reduxForm } from 'redux-form/immutable';
import { connect } from 'react-redux';
import { logUserIn } from '../../actions/authentication';
import { VALID_EMAIL_REGEX } from '../../config/app_config';
import LoginForm from './LoginForm';
const FORM_ID = 'loginForm';
export class LoginFormContainer extends React.Component {
static propTypes = {
handleSubmit: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
loginAction: PropTypes.func.isRequired,
};
performLogin = (params) => {
const { loginAction } = this.props;
const credentials = {
email: params.email,
password: params.password,
};
loginAction(credentials, '/home');
}
render() {
const { handleSubmit, submitting } = this.props;
return (
<LoginForm
handleSubmit={ handleSubmit }
loginFunction={ this.performLogin }
submitting={ submitting }
/>
);
}
}
const validate = values => {
const errors = {};
if (!values.email || values.email === '') {
errors.email = 'Required';
}
else if (!VALID_EMAIL_REGEX.test(values.email)) {
errors.email = 'Invalid email address';
}
if (!values.password || values.password === '') {
errors.password = 'Required';
}
return errors;
};
LoginFormContainer = reduxForm({
form: FORM_ID,
validate,
})(LoginFormContainer);
export default connect(null, {
loginAction: logUserIn,
})(LoginFormContainer);
I am passing down my submission handler function as a prop to my actual form that contains the Field component for inputs. The loginAction will link to the action for redux to send the values to the backend and redirect to home.
import React, { PropTypes } from 'react';
import { Field } from 'redux-form/immutable';
import { getClassName, checkButtonDisabled } from '../../utils/forms';
import { Link } from 'react-router';
const renderInput = (field) => {
return (
<div className={ getClassName(field.meta.touched, field.meta.error) }>
<input
{...field.input}
className="form-control form-control-success"
type={field.type}
/>
{field.meta.touched &&
field.meta.error &&
<span className="error">{field.meta.error}</span>}
</div>
);
};
export default class LoginForm extends React.Component {
static propTypes = {
handleSubmit: PropTypes.func.isRequired,
loginFunction: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
};
render() {
const {
loginFunction,
submitting } = this.props;
return (
<form onSubmit={ loginFunction.bind(this) }>
<fieldset>
<div>
<label className="form-control-label">
Email address
</label>
<Field
name="email"
component={renderInput}
type="text"
placeholder="example#exampledomain.com"
/>
</div>
<div>
<label className="form-control-label">
Password
</label>
<Field
name="password"
component={renderInput}
type="password"
placeholder="your password"
/>
</div>
</fieldset>
<button
type="submit"
className="btn btn-primary"
disabled={ checkButtonDisabled(submitting) }
>
Log In
</button>
<Link to="/forgot-password">Forgot Password?</Link>
</form>
);
}
}
I successfully was able to get the form to work but when I hit login I get the error above and I am redirected to home, but I am not authenticated and I get a 422 error as well. I couldn't tell if my form connecting is the only error or if my action is not getting the right information from the form submission function.
Got any suggestions?
You are redirected home, because your loginFunction() is fired, but the form is not submitted
There are a couple of things that need to be updated. Your <form> tag must have a corresponding id and it should handle submit by passing your function to redux-form inbuilt submit handler. So you modifying LoginForm class as follows should get the form working
<form id="loginForm" onSubmit={ handleSubmit(this.loginFunction.bind(this)) } >
More about internal redux-form method handleSubmit here: http://redux-form.com/6.5.0/docs/api/Form.md/
Using the answer given to me above I just wanted to clarify what I did to solve the issue.
I grabbed the handleSubmit method that comes from the reduxForm and passed it to the LoginForm as a prop from the container that also retrieved it from the props.
I also imported the Form component from redux-form on the LoginForm component and just simply replaced the normal JSX tag with .
here were the final changes I made.
LoginForm.jsx:
//Added Form from redux-form
import { Field, Form } from 'redux-form/immutable';
render() {
const {
handleSubmit,//defined handleSubmit function from props which comes from the reduxForm being exported to the state.
loginFunction,
submitting } = this.props;
return (
//replaced <form></form> with <Form></Form>
<Form id="loginForm" onSubmit={ handleSubmit(loginFunction.bind(this)) }>
//passed my loginFunction into the handleSubmit function
//added an id to <Form> that corresponds to the forms id that was passed in reduxForm({ form: 'loginForm' })
<fieldset>
<div>
<label className="form-control-label">
Email address
</label>
<Field
name="email"
component={renderInput}
type="text"
placeholder="example#exampledomain.com"
/>
</div>
<div>
<label className="form-control-label">
Password
</label>
<Field
name="password"
component={renderInput}
type="password"
placeholder="your password"
/>
</div>
</fieldset>
<button
type="submit"
className="btn btn-primary"
disabled={ checkButtonDisabled(submitting) }
>
Log In
</button>
<Link to="/forgot-password">Forgot Password?</Link>
</Form>
);

Why can't I type in my fields?

I am using redux-form and I cannot type inside of my inputs after I add the initialize method and componentDidUpdate(). When I try to type in my email no characters appear. I am guessing all the inputs become controlled? If so how would I handle that?
import { reduxForm, Field, initialize } from 'redux-form';
const CustomComponent = function(field) {
return(
<div>
<input { ...field.input } type={field.type} placeholder={field.placeholder} />
</div>
);
}
//class instantiation
componentDidUpdate(){
this.handleInitialize();
}
handleInitialize() {
const initData = {
"name": this.props.name
};
this.props.initialize(initData);
}
render() {
const { handleSubmit } = this.props;
return (
<div>
<form onSubmit={handleSubmit(this.onSubmit)}>
<div>
<Field name="name" component={CustomComponent} type="text" placeholder="Name" />
<Field name="email" component={CustomComponent} type="email" placeholder="Email" />
</div>
<button type="submit">Submit</button>
</form>
</div>
);
}
You can't define your CustomComponent inside the render() method. That will cause your component to lose focus when you first start typing into an input.
Have you set up the reducer properly in your Redux config?

Resources