Simple Redux form using react redux - reactjs

In the execution of the below code snippet I'm getting the following error.
Error: Field must be inside a component decorated with reduxForm()
src/components/LoginForm/index.js
import React, {Component} from 'react';
import {Field, reduxForm} from 'redux-form';
class LoginForm extends Component {
render () {
const {handleSubmit} = this.props;
return (
<form onSubmit={handleSubmit}>
<Field
name="username"
component="input"
type="text"
placeholder="Username"
/>
<Field
name="password"
component="input"
type="password"
placeholder="Password"
/>
<button type="submit" label="submit">Submit</button>
</form>
);
}
}
export default reduxForm({
form: 'simpleform'
})(LoginForm)

Try this and also it is class component not a functional component so how you imported your LoginForm in the App.js
Import like this
import LoginForm from 'LoginForm'; // Default export
and export like this:
LoginForm= reduxForm({
form: 'simpleform'
})(LoginForm)
export default LoginForm;

Making your class component to a functional component may be the solution. Just try this out.
import React from "react";
import { Field, reduxForm } from "redux-form";
const LoginForm = props => {
const { handleSubmit } = props;
return (
<form onSubmit={handleSubmit}>
<Field
name="username"
component="input"
type="text"
placeholder="Username"
/>
<Field
name="password"
component="input"
type="password"
placeholder="Password"
/>
<button type="submit" label="submit">
Submit
</button>
</form>
);
};
export default reduxForm({
form: "simpleform"
})(LoginForm);

Related

Multiple redux form rendering failure

Hi I am trying to implement multiple redux forms. But I am getting the same redux form in the output. Could someone look into this and tell me where I am going wrong:
Form 1: Signup.js
import React from 'react';
import {Field,reduxForm} from 'redux-form';
const validate = values =>{
const errors={};
if(!values.username){
errors.username="Please Enter Username";
}else if(values.username.length<5){
errors.username='Please enter atlease 5 characters';
}
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'
}
if(!values.password){
errors.password='Please enter password'
}
return errors;
}
const renderField = ({ input, label, type, meta: { touched, error } }) => (
<div>
<label>{label}</label>
<div>
<input {...input} placeholder={label} type={type}/>
{touched && ((error && <span>{error}</span>))}
</div>
</div>
)
const SyncValidationForm = (props) => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<Field name="username" type="text" component={renderField} label="Username"/>
<Field name="email" type="email" component={renderField} label="Email"/>
<Field name="password" type="password" component={renderField} label="Password"/>
<div>
<button type="submit" disabled={submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>Clear Values</button>
</div>
</form>
)
}
export default reduxForm ({
form: 'syncValidation',
validate
})(SyncValidationForm)
Form 2: Login.js
import React from 'react';
import {Field, reduxForm} from 'redux-form';
const renderField = ({input, label, type})=>{
<div>
<label>{label}</label>
<div>
<input {...input} placeholder={label} type={type}/>
</div>
</div>
}
const Login = (props) =>{
const {handleSubmit} = this.props;
return(
<form onSubmit={handleSubmit}>
<div>
<Field name='username' component={renderField} type='text' label='Username'/>
<Field name='password' type='password' component={renderField} label='Password'/>
</div>
<div>
<button type='submit' disabled={submit}>Submit</button>
</div>
</form>
)
}
export default reduxForm ({
form:'login'
})(Login);
Rendering Component: Homepage.js
import React from 'react';
import {connect} from 'react-redux';
import SyncValidationForm from "../Form/signup";
import Login from "../Form/signup";
class Homepage extends React.Component{
render(){
return(
<div>
<SyncValidationForm onSubmit={this.props.addition}/>
<Login />
</div>
)
}
}
var matchStatetoProps = state =>{
return {root:state.root}
}
var matchDispatchtoProps = dispatch =>{
return{addition:(values)=>dispatch({type:'ADD',payload:values})}
}
export default connect(matchStatetoProps,matchDispatchtoProps)(Homepage);
Store:
import { createStore, combineReducers } from 'redux';
import { reducer as reduxFormReducer1 } from 'redux-form';
import { reducer as reduxFormReducer2 } from 'redux-form';
import rootReducer from '../Reducers/rootReducer'
const reducer = combineReducers({
form: reduxFormReducer1,
login:reduxFormReducer2,
root: rootReducer
});
const store = (window.devToolsExtension
? window.devToolsExtension()(createStore)
: createStore)(reducer);
export default store;
Now its giving an output something like this:
Could someone help me in where I am going wrong
Sorry I was importing the wrong form.

No data passed in submit method of Redux-form

I want to send the input values to the api.
I used the code from below link, to get the input values in the submit method, but though the submit method gets called, the variable is empty.
How to handle redux form submitted data
index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import ContactForm from "./ContactForm";
import * as serviceWorker from "./serviceWorker";
import { createStore } from "redux";
import { Provider } from "react-redux";
import rootReducers from "./reducers";
const store = createStore(rootReducers);
ReactDOM.render(
<Provider store={store}>
<ContactForm />
</Provider>,
document.getElementById("root")
);
serviceWorker.unregister();
reducer.js
import { combineReducers } from "redux";
import { reducer as formReducer } from "redux-form";
const rootReducer = combineReducers({
form: formReducer
});
export default rootReducer;
ContactForm.js
import React, { Component } from "react";
import { reduxForm } from "redux-form";
class ContactForm extends Component {
submit(formValues) {
console.log(formValues);
}
render() {
const {
fields: { firstName, lastName, email },
handleSubmit
} = this.props;
return (
<form onSubmit={handleSubmit(this.submit)}>
<div>
<label>First Name</label>
<input type="text" placeholder="First Name" {...firstName} />
</div>
<div>
<label>Last Name</label>
<input type="text" placeholder="Last Name" {...lastName} />
</div>
<div>
<label>Email</label>
<input type="email" placeholder="Email" {...email} />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
ContactForm = reduxForm({
form: "contact",
fields: ["firstName", "lastName", "email"]
})(ContactForm);
export default ContactForm;
I am getting formValues as empty. Could anyone please help me with it?
It seems the example was for version 5.3.1 of Redux-form, while I had installed 8.1.0 version.
Below is the working code:
import React, { Component } from "react";
import { Field, reduxForm } from "redux-form";
const submit = values => {
console.log(values);
};
class ContactForm extends Component {
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(submit)}>
<div>
<label>First Name</label>
<Field name="firstName" component="input" type="text" />
</div>
<div>
<label>Last Name</label>
<Field name="lastName" component="input" type="text" />
</div>
<div>
<label>Email</label>
<Field name="email" component="input" type="email" />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
export default reduxForm({
form: "contact"
})(ContactForm);
You probably need to use instead of inside the form, to connect your input data with redux store.
https://redux-form.com/8.3.0/examples/submitvalidation/

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 error on handleSubmit

I am getting error while using redux-form
Error msg in console:
bundle.js:32511 Uncaught Error: You must either pass handleSubmit()
an onSubmit function or pass onSubmit as a prop(…)
the above error appeared on page load and button click
Please refer to the below code sample which cause the console error.
import React, { Component } from 'react';
import { reduxForm } from 'redux-form';
import { createPost } from '../actions/index';
class PostsNew extends Component {
render() {
const { fields: { title, categories, content }, handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.props.createPost)}>
<h3>Create a new Post</h3>
<div className="form-group">
<label>Title</label>
<input type="text" className="form-control" {...title}/>
</div>
<div className="form-group">
<label>Categories</label>
<input type="text" className="form-control" {...categories}/>
</div>
<div className="form-group">
<label>Content</label>
<textarea className="form-control" {...content}/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
);
}
}
export default reduxForm({
form: 'PostsNewForm',
fields: ['title', 'categories', 'content']
}, null, { createPost })(PostsNew);
This was a step by step follow of StephenGrider redux tutorial
Thanks in advance :)
If PostsNew is Container (if this is directly invoked form Routes) then you have to make handleSubmit function instead of taking from this.props
import React, { Component } from 'react';
import { reduxForm } from 'redux-form';
import { createPost } from '../actions/index';
class PostsNew extends Component {
handleSubmit(formValues){
console.log(formValues);
//do what ever you want
}
render() {
const { fields: { title, categories, content } } = this.props;
return (
<form onSubmit={this.handleSubmit(this.props.createPost)}>
<h3>Create a new Post</h3>
<div className="form-group">
<label>Title</label>
<input type="text" className="form-control" {...title}/>
</div>
<div className="form-group">
<label>Categories</label>
<input type="text" className="form-control" {...categories}/>
</div>
<div className="form-group">
<label>Content</label>
<textarea className="form-control" {...content}/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
);
}
}
OR
In case PostsNew is React Component that is used inside a Container then you can pass handleSubmit in props of PostsNew
<PostsNew
handleSubmit={ (values) => {console.log(values)}}
/>
You need to pass onsubmit props from parent component
import React from 'react';
import { connect } from 'react-redux';
import { initialize } from 'redux-form';
import PostsNew from './PostsNew';
class App extends React.Component {
handleSubmit(data) {
console.log('Submission received!', data);
this.props.dispatch(initialize('contact', {})); // clear form
}
render() {
return (
<div id="app">
<h1>App</h1>
<PostsNew onSubmit={this.handleSubmit.bind(this)}/>
</div>
);
}
}
export default connect()(App);
I was running into the same problem until I explicitly imported connect into my file. After that, I was able to call this.props.createPost successfully.
This is my solution:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form'
import { createPost } from '../actions/index';
import { connect } from 'react-redux';
class PostsNew extends Component {
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.props.createPost)}>
<h3>Create a New Post</h3>
<div className="form-group">
<label>Title</label>
<Field name="title" component="input" type="text" className="form-control" placeholder="Title" />
</div>
<div className="form-group">
<label>Categories</label>
<Field name="categories" component="input" type="text" className="form-control" placeholder="Title" />
</div>
<div className="form-group">
<label>Content</label>
<Field name="content" component="textarea" type="text" className="form-control" placeholder="Title" />
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
);
}
}
export default connect(null, {createPost})(reduxForm({
form: 'PostsNew'
})(PostsNew));
This works perfectly. Check your action creator there should be a typo error in your action creator. Please refer the below action creator. If you followed the steps as he mentioned, this should work perfectly. What the error says is you don't have something called createPost in your props. Further more you can find my working project here in github.
export function createPost(props) {
console.log(props);
const request = axios.post(`${ROOT_URL}/posts${API_KEY}`, props);
return {
type: CREATE_POST,
payload: request
};
}
please install version 5 of redux-form.
npm install --save redux-form#5

Resources