why the page refresh on button click in react? - reactjs

could you please tell me why the page refresh on button click in react ? I enter something in input field and press button, my page is refresh
I want to get the value of form field
https://codesandbox.io/s/green-frost-414qi
class ContactForm extends React.Component {
handleSubmit = values => {
// print the form values to the console
console.log(values);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text" />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;

It's standard behavior for forms to refresh the page after submit events. To stop this you can add event.preventDefault()
handleSubmit = event => {
event.preventDefault()
console.log(event.target.firstName.value); //get value from input with name of firstName
};
With Redux-Forms, in order to get the values object and not have the page refresh, we have to use the event-handler that's been created for us by Redux-form. It's created when we pass an onSubmit prop like so to the Form component:
<ContactRForm onSubmit={this.submit} />
Interestingly enough, that handler is now available through the prop handleSubmit(), which I expect has its own event.preventDefault() built in.
Try adding this to your Form component-code:
import React from "react";
import { Field, reduxForm } from "redux-form";
class ContactForm extends React.Component {
render() {
return (
<form onSubmit={this.props.handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text" />
<label htmlFor="lastname">Last Name</label>
<Field name="lastname" component="input" type="text" />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;
Now the same functionality of the original submit function occurs and the page does not refresh. :)

You can achieve this using below changes.
class ContactForm extends React.Component {
constructor(props){
super(props);
this.state = {
fieldValue : ''
}
this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
updateInput(event){
this.setState({username : event.target.value})
}
handleSubmit = event=> {
// print the form values to the console
event.preventDefault() // this is used to prevent the form submission
console.log('Your input value is: ' + this.state.username) // your input field value
};
render() {
return (
<form>
<div>
<label htmlFor="firstName">First Name</label>
<Field value={input} onChange={this.updateInput} /> // set the input value
</div>
<button type="submit" onClick={this.handleSubmit} >Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;

This is default behavior of HTML forms to refresh page on submit button. You can stop refresh by adding event.preventDefault();
For more details you can read ReactJS Form documentation
handleSubmit = e => {
event.preventDefault()
// get form value by accessing target values
console.log(e.target.firstName.value);
};

Related

Setting the default value of an input field after data is retrieved causes the content to overlap and the "onChange" event not to be triggered

I have an "edit category" component in my React application.
The ID is passed through the URL.
When the component is mounted, the action "fetchCategory" is called, which updates the props on the component with the current category.
I have a form which I want to be pre-populated, which I'm currently doing using the defaultValue on the input.
However, this isn't reflected on the state and the label for the text field overlaps the input field.
Any help would be greatly appreciated. I'll leave snippets of my code below which could help with understanding what I'm trying to do.
import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchCategory } from "../../store/actions/categoryActions";
class AddOrEditCategory extends Component {
componentDidMount() {
this.props.fetchCategory(this.props.match.params.id);
if (this.props.match.params.id) {
this.setState({
_id: this.props.match.params.id
});
}
}
handleSubmit = e => {
e.preventDefault();
console.log(this.state);
};
handleChange = e => {
this.setState({
[e.target.id]: e.target.value
});
};
render() {
const addingNew = this.props.match.params.id === undefined;
return (
<div className="container">
<h4>{addingNew ? "Add category" : "Edit category"}</h4>
<form onSubmit={this.handleSubmit}>
<div className="input-field">
<input
type="text"
id="name"
defaultValue={this.props.category.name}
onChange={this.handleChange}
/>
<label htmlFor="name">Category name</label>
</div>
<div className="input-field">
<input
type="text"
id="urlKey"
onChange={this.handleChange}
defaultValue={this.props.category.urlKey}
/>
<label htmlFor="urlKey">URL Key</label>
</div>
<button className="btn">{addingNew ? "Add" : "Save"}</button>
</form>
</div>
);
}
}
const mapStateToProps = state => {
return {
category: state.categoryReducer.category
};
};
export default connect(
mapStateToProps,
{ fetchCategory }
)(AddOrEditCategory);
EDIT: Included whole component as requested
You need to replace the 'defaultValue' attribute with 'value' in the inputs.
You are using a controlled vs uncontrolled component. You dont need to use defaultValue.
You can set the initial values on the promise success for fetchCategory
componentDidMount() {
this.props.fetchCategory(this.props.match.params.id).then(response => {
// Set the initial state here
}
}
OR in
componentWillReceiveProps(nextProps) {
// Compare current props with next props to see if there is a change
// in category data received from action fetchCategory and set the initial state
}
React docs
<form onSubmit={this.handleSubmit}>
<div className="input-field">
<input
type="text"
id="name"
onChange={this.handleChange}
value={this.state.name} //<---
/>
<label htmlFor="name">Category name</label>
</div>
<div className="input-field">
<input
type="text"
id="urlKey"
onChange={this.handleChange}
value={this.state.urlKey}
/>
<label htmlFor="urlKey">URL Key</label>
</div>
<button className="btn">{addingNew ? "Add" : "Save"}</button>
</form>

redux-form: Passing an _id to the submit handler along with formProps

I'm building an edit button for my CRUD app. In this component, each individual 'rating' is mapped into one of these components. The component starts out be displaying the rating as stored in the DB, but users can press the edit button, and it turns into a form! (eventually, I'll get initial values to populate the form fields with the data displayed in the alternate render option).
Right now for the edit button, I have a custom submit handler receiving the submitted data from the two form fields as 'formProps'. However, before passing these off to the backend API, I ALSO need to figure out how to tie an id or something to the submit handler.
As seen in the component right below the form, this whole child component has access to the necessary passed down from the parent which can accessed as 'this.props.id'. Is there anyway to bundle 'this.props.id' with formProps before the handleSubmit takes it all to Redux Actions?
class Rating extends Component{
constructor(props){
super(props);
this.state = {
formClass: "notShowing",
ratingClass: "showing"
}
}
renderForm = () => {
this.state.formClass === "notShowing"
? this.setState({formClass: "showing", ratingClass: "notShowing"})
: this.setState({formClass: "notShowing", ratingClass: "showing"})
}
onSubmit = (formProps) => {
console.log("this is what the submitHandler recieves;", formProps);
this.props.editRating(formProps, () => {
this.props.history.push('/userDashboard');
});
}
render() {
const { handleSubmit, reset } = this.props;
return (
<div className="card darken-1" key={this.props._id}>
<div className={this.state.formClass}>
<form onSubmit={handleSubmit(this.onSubmit)}>
<p>What are you rating?</p>
<fieldset>
<Field
name="title"
type="text"
component="input"
autoComplete="none"
/>
<p>Add your rates!</p>
<Field
name="value"
type="number"
component="input"
autoComplete="none"
/>
</fieldset>
<button onClick={this.renderForm} type="submit" className="teal btn-flat right white-text">Submit</button>
</form>
<button onClick={this.renderForm}>Cancel</button>
</div>
<div className={this.state.ratingClass}>
<div className="card-content">
<span className="card-title">{this.props.title}</span>
<p>{this.props.value}</p>
<button onClick={this.renderForm}>Edit</button>
<button onClick={() => this.props.deleteRating(this.props.id)}>Delete</button>
</div >
</div>
</div>
);
}
}
function mapStateToProps({ratings}) {
return { ratings };
}
export default compose(
connect(mapStateToProps, actions),
reduxForm({ form: 'editRating' })
)(Rating);
You can use the third parameter of the handleSubmit function.
onSubmit = (values, _, props) => {
console.log(values, props.id);
...
}
...
const { handleSubmit, reset } = this.props;
<form onSubmit={handleSubmit(this.onSubmit)} .../>
Reference: https://redux-form.com/7.4.2/docs/api/reduxform.md/#-code-onsubmit-function-code-optional-

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));

how to provide validations for react js form

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")
}

Submitting redux form values

I am new to react and redux technology. now started building an application that contains several redux forms. We want to submit simple form with values.
For ex: login form
Username : text input field
Password: text input field
Submit button
After entering values in fields and click on submit button i want to get the username and password field values in object or json data .. so that I can store it to my server with POST method.
Right now we are using handleSubmit(), but data is not coming as object
1 - The best practice to deal with input values are making them controlled. Which means :
Instead of
<input type='password' />
You do :
<input
type='password'
value={password}
onChange={ event => myInputHandler( event.target.value ) }
/>
The value might come from your state, redux state or as a props etc.
Your handler function differs according to where you store it.
I will give you an example with react state :
<input
type='password'
value={this.state.password}
onChange={ event => this.setState({ password : event.target.value }) }
/>
So whenever someone types, your onChange handler will be called, so that your react state will update with the input ( event.target.value ).
2 - If you need these values when a user submits, then you need to wrap these input fields within a form element and attach a onSubmit handler.
onSubmitHandler( event ){
event.preventDefault()
let password = this.state.password
// use password or other input fields, send to server etc.
}
<form onSubmit={ event => this.onSubmitHandler(event) }>
<input
type='password'
value={this.state.password}
onChange={ event => this.setState({ password : event.target.value }) }
/>
</form>
Hope you get what you need.
If you are using redux to store state then use redux-from then use redux from
import React from 'react'
import {Field, reduxForm} from 'redux-form'
const SimpleForm = props => {
const {handleSubmit, submitting} = props return (
<form onSubmit={handleSubmit(e=>console.log('your form detail here', e))}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" placeholder="First Name" />
</div>
</div>
<div>
<label>Last Name</label>
<div>
<Field name="lastName" component="input" type="text" placeholder="Last Name" />
</div>
</div>
<div>
<button type="submit" disabled={pristine || submitting}>Submit</button>
</div>
</form>
) }
export default reduxForm({ form: 'simple'})(SimpleForm)
Go here for more detail
https://redux-form.com
I put the name of the input as the key that I want to use.
Then each time the input changes I destructure the event passed to the onChange function, and I use the name,value to update the state.
On form submit make sure to use preventDefault(); in order to avoid the page refreshing.
import React, { Component } from 'react'
class FormExample extends Component {
constructor(props){
super(props)
this.state = {
formData: {}
}
}
handleInputChange = ({ target: { name,value } }) => {
this.setState({
formData: {
...this.state.formData,
[name]: value
}
})
}
handleFormSubmit = e => {
e.preventDefault()
// This is your object
console.log(this.state.formData)
}
render() {
return(
<div>
<Form
handleSubmit={this.handleFormSubmit}
handleChange={this.handleInputChange}
/>
</div>
)
}
}
const Form = ({ handleSubmit, handleChange }) => (
<form onSubmit={handleSubmit}>
<input onChange={handleChange} name="username" type="text" placeholder="Username" />
<input onChange={handleChange} name="password" type="password" placeholder="Password" />
<button>Submit</button>
</form>
)
export default FormExample

Resources