I'm creating a simple login form using react and redux form.
When I try to console the values entered in the form, I get undefined.
import React, { Component } from 'react';
import { reduxForm } from 'redux-form';`enter code here`
class Signin extends Component {
handleFormSubmit({email, password}){
console.log(email,password);
// this.props.signinUser({email,password});
}
render(){
const { handleSubmit, fields: { email, password }} = this.props;
return (
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
<fieldset className="form-group">
<label>Email:</label>
<input className="form-control" {...email} />
</fieldset>
<fieldset className="form-group">
<label>Password:</label>
<input className="form-control" {...password} />
</fieldset>
<button action="submit" className="btn btn-primary">Sign in</button>
</form>
);
}
}
export default reduxForm({
form: 'signin',
fields: ['email', 'password']
})(Signin);
I figured out the issue.
The tutorial I was following was one year old and was using an old version of Redux Form which accepts input in this form. But while installing the modules, I installed the latest version. Thanks.
Related
I cannot type in the text input of redux form.
it's a very minimal form
function Login({ handleSubmit, handleChange }) {
const [username, setUsername] = useState(undefined);
const [password, setPassword] = useState(undefined);
const onSubmit = (e) => {
console.log(e);
console.log(username);
console.log(password);
};
console.log(handleSubmit);
return (
<Container>
<div className={styles.centered}>
<div className={styles.form}>
<div className={styles.title}>
<H3>Login</H3>
</div>
<form onSubmit={() => handleSubmit(onSubmit)} className={styles.flexColumn}>
<div className={styles.username}>
<P>username</P>
<Field name="username" component="input" type="text" className={styles.input} />
</div>
<div className={styles.password}>
<P>password</P>
<Field name="password" component="input" type="password" className={styles.input} />
</div>
<div className={styles.downSection}>
<Flex>
<P>
Serve Aiuto?
</P>
<a href="#">
<div className={styles.contactLink}>
<P>Contattaci</P>
</div>
</a>
</Flex>
<Button type="submit" text="Accedi" />
</div>
</form>
</div>
</div>
</Container>
);
}
const mapDispatchToProps = {
login: loginAction,
};
const enhance = compose(
connect(null, mapDispatchToProps),
reduxForm({ form: 'login' }),
);
export default enhance(Login);
The handleSubmit doesn't work, i cannot console.log anything.
I tried to see the documentation and tried to search some answer on SO but i didn't find an answer.
Could you please tell me where is the error ? thanks.
So give this a try, let's leave enhance out, I don't know what it does honestly so let's try this type of Login configuration where we turn the component into a class-based one which is good practice anyway since you are receiving inputs from a user.
I do realize you are using useState which is some of the cool new features with React, but what I am recommending is to put together a less complex and conventional setup with a class-based component like so:
import React, { Component } from "react";
import { reduxForm, Field } from "redux-form";
class Login extends Component {
render() {
return (
<form>
<fieldset>
<label>Email</label>
<Field
name="email"
type="text"
component="input"
/>
</fieldset>
<fieldset>
<label>Password</label>
<Field
name="password"
type="password"
component="input"
/>
</fieldset>
</form>
);
}
}
export default reduxForm({ form: "login" })(Login);
Use this to check to see if you can now type into your inputs and then start adding stuff back in and test it every single time until you find the cause of the problem.
Try first just to handle the event
<form onSubmit={onSubmit} className={styles.flexColumn}>
after that try using the this in the function onsubmit and remove the const
onSubmit(event){
console.log(e);
console.log(username);
console.log(password);
this.handleSubmit(event.target.value);
};
after several hours and a special night of bug fixing i discovered the problem:
it was in one import, exactly:
import { Field, reduxForm } from 'redux-form/immutable';
and not
import { Field, reduxForm } from 'redux-form';
this was completely unexpected, i was pretty sure that the mistake was in the body of the component, not in the import.
the structure of the file was ok.
I have just started learning reactjs. I came across formik and yup while searching for form validation. Most of the examples that i have gone through so far are talking about stateless components. So I would like to know how can I use formik and yup in a stateful component?
I have got a simple employee details form with email,first name, last name, phone and city. The data for the form is loaded from the database. Once the data is loaded, then user can edit and save it to db. Could you please help me to add formik and yup into my project by adding validation for all my above fields? My Code is also present here https://codesandbox.io/s/l26rqyx6j7
My form is given below EmpJobDetailsForm.js
import React from "react";
import { getEmpDetails } from "./APIUtils";
import { withFormik, Form, Field } from "formik";
import Yup from "yup";
class EmpJobDetailsForm extends React.Component {
state = {
data: {}
};
componentWillMount() {
this.getData();
}
getData = () => {
let response = getEmpDetails();
this.setState({ data: response });
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<div>
<label htmlFor="email">Email</label>
<input type="email" name="email" value={this.state.data.email} />
</div>
<div>
<label htmlFor="firstName">First Name</label>
<input
type="text"
name="firstName"
value={this.state.data.firstName}
/>
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<input
type="text"
name="lastName"
value={this.state.data.lastName}
/>
</div>
<div>
<label htmlFor="phone">Phone</label>
<input type="text" name="phone" value={this.state.data.phone} />
</div>
<div>
<label htmlFor="city">City</label>
<input type="text" name="city" value={this.state.data.city} />
</div>
<div>
<button type="button" className="outline">
Reset
</button>
<button type="submit">Submit</button>
</div>
</form>
</div>
);
}
}
export default EmpJobDetailsForm;
I have a simple APIUtils.js. It is very basic and i will add code to fetch data from db here.
export function getEmpDetails() {
var employeeData = {};
employeeData.email = "test#gmail.com";
employeeData.firstName = "Luis";
employeeData.middleName = "John";
employeeData.lastName = "Nakano";
employeeData.phone = "1112223333";
employeeData.city = "Dallas";
return employeeData;
}
Appreciate your help.
Thanks
Formik is stateful, it's first goal is to "Getting values in and out of form state" (without using Redux-Form).
A cleaner way to do this would be to use a Formik form and to add your fetched data as initalValues (but first remove all the value attributes from your current inputs).
You can also take a look at the 'withFormik' higher-order component and particularly the mapsPropsToValues option.
How to provide validations for react js form.
I have taken form with two fields. if two fields are enabled then only need to enable save button.
import React from 'react'
import { Button, Checkbox, Form } from 'semantic-ui-react'
const FormExampleForm = () => (
<Form>
<Form.Field>
<label>First Name</label>
<input placeholder='First Name' />
</Form.Field>
<Form.Field>
<label>Last Name</label>
<input placeholder='Last Name' />
</Form.Field>
<Form.Field>
<Checkbox label='I agree to the Terms and Conditions' />
</Form.Field>
<Button type='submit'>Submit</Button>
</Form>
)
export default FormExampleForm
In redux forms 6.7 there's a simple property called pristine which can be used to do this. But if the user enters some value in at least one input field the submit button gets activated. To achieve that you may need to do something like this.
render() {
// const { handleSubmit } = this.props;
const {handleSubmit, pristine, reset, submitting} = this.props
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" placeholder="First Name"/>
</div>
</div>
<button type="submit" className="btn btn-primary" disabled={pristine || submitting}>Submit</button>
</form>
);
}
}
But if you need to enable submit button, say when the user inputs values in 2 given fields or so, then this becomes complex. You need to do something like this. Here's my sample usecase. The form has 3 fields firstName, lastName and age. The submit button gets activated only if the user enters values for firstName and lastName input fields here. Please check out the following code.
import React, { Component } from 'react';
import { Field, reduxForm, formValueSelector } from 'redux-form';
import { connect } from 'react-redux';
class UserNew extends Component {
constructor(props) {
super(props);
this.isSubmitEnabled = this.isSubmitEnabled.bind(this);
}
onSubmit(values) {
console.log(values);
}
isSubmitEnabled() {
// Access field values here and validate them
const firstName = this.props.firstNameValue;
const lastName = this.props.lastNameValue;
if(firstName && lastName){
return true;
}
return false;
}
render() {
const { handleSubmit } = this.props;
const isEnabled = this.isSubmitEnabled();
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" />
</div>
</div>
<div>
<label>Last Name</label>
<div>
<Field name="lastName" component="input" type="text" />
</div>
</div>
<div>
<label>Age</label>
<div>
<Field name="age" component="input" type="text" />
</div>
</div>
<button type="submit" className="btn btn-primary" disabled={!isEnabled}>Submit</button>
</form>
);
}
}
UserNew = reduxForm({
form: 'UserNewForm'
})(
UserNew
);
// Decorate with connect to read form values
const selector = formValueSelector('UserNewForm') // <-- same as form name
UserNew = connect(state => {
const firstNameValue = selector(state, 'firstName')
const lastNameValue = selector(state, 'lastName')
return {
firstNameValue,
lastNameValue,
}
})(UserNew)
export default UserNew;
To access field values you need to use formValueSelector in ReduxForms. For that you need to connect your form to redux store using connect helper.
Hope this helps. Happy coding !
Either you can use Redux-form as its not used in above code, so you can write custom JS validation code. For this you need to follow below
Initialise state in
contructor(){
this.state{
first_name: null,
last_name: null,
}
}
Change state of every input element onChange onChange={()=>this.setState({first_name: event.target.value})}
Now add onClick property to <Button onClick={this.handleSubmit} />
inside handleSubmit() you can get values through local state of component and add validation rules like
if(this.state.first_name =="") {
console.log("Enter first name")
}
I am working on a React-Redux app, currently working on showing a modal box on a button click of a form. But I can't make it work. I have tried so many things but can't figure out why the modal box doesn't appear. Here is my code.
The Modal component file
import React from 'react'
import { connectModal } from 'redux-modal'
import { Button, Modal } from 'react-bootstrap'
import UpdatePasswordForm from 'forms/updatepassword'
export class UpdatePassword extends React.Component {
constructor(props) {
super(props)
}
renderCloseIcon (handleHide) {
return (
<button className='close' onClick={ handleHide }>
<span>
<i className="modal__close"/>
</span>
</button>
)
}
renderModalLogo () {
return (
<div className="modal__header modal__header_login">
<div className="modal__logo"></div>
</div>
)
}
render() {
const { show, handleHide } = this.props
return (
<Modal
show={ show }
onHide={ handleHide }
backdrop={ true }
className="modal_dark modal_center"
dialogClassName="modal-background-fix">
<div className="modal__container">
{ this.renderCloseIcon(handleHide) }
{ this.renderModalLogo() }
<div className="modal__content">
<UpdatePasswordForm onSubmit={() => {}}/>
</div>
</div>
</Modal>
)
}
}
export default connectModal({name: 'updatepassword'})(UpdatePassword)
The form that is loaded in the Modal
import React from 'react'
import { Field, reduxForm } from 'redux-form'
import Text from '../containers/Text'
const I18n = {}
I18n.t = Text.t
const UpdatePasswordForm = (props) => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<fieldset className="form-group">
<Field name="current_password" component="input"
type="password" placeholder="Password" className="form-control" />
</fieldset>
<fieldset className="form-group">
<Field name="password" component="input"
type="password" placeholder="New Password" className="form-control" />
</fieldset>
<fieldset className="form-group">
<Field name="password_confirm" component="input" type="password"
placeholder="New password confirmation" className="form-control" />
</fieldset>
<fieldset className="form-group form-group_btns">
<button type="submit" disabled={pristine || submitting} className="btn btn-primary btn-block">
{ 'CHANGE PASSWORD' }
</button>
</fieldset>
</form>
)
}
export default reduxForm({
form: 'updatepassword' // a unique identifier for this form
})(UpdatePasswordForm)
The file where modal is called
import React from 'react';
import './EditInformation.scss'
import { show } from 'redux-modal'
import UpdatePassword from './Modals/UpdatePassword'
// TODO fix stylee stylee
// TODO onChange is not updating correctly, FIX!
const EditInformation = ({ onSubmit, onChange, user, formSubmitting }) => {
return (
<div>
<UpdatePassword />
<form className='form-line form-line_light'>
<div className='col-xs-16 col-sm-8'>
<fieldset className='form-group'>
<button
onClick={(e) => {
show('updatepassword')
e.preventDefault()
}}
className='btn btn-secondary btn-lg profile-edit__addcard'
style={ { position: 'relative', top: '-27px' } }>
<i className='fa fa-plus'/>Vaihda salasana
</button>
</fieldset>
</div>
</form>
</div>
);
};
export default EditInformation;
In the beginning of our project, I tried to develope my own modal with all custom functionalities. Many problems has occured. I searched some open source projects, then I found a project on github. You should use react-modal, It's easy to use and well designed.
react-modal
There was a stupid mistake that I have figured out now. But I should get an error for that which I am not getting. I had to pass 'show' to the const EditInformation which I have done now and it is working all fine. Here is that part of the code:
const EditInformation = ({ onSubmit, onChange, user, formSubmitting, show }) => {
I wasn't passing 'show' previously.
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