Why e.preventDefault() does not work in React? - reactjs

Basic code below, yet the form submits and reloads. Why?
import React from 'react';
class TestSubmitComponent extends React.Component {
constructor(props) {
super(props);
}
formSubmitHandler = (e) => {
e.preventDefault(); //should prevent submit, and continue below?
console.log(e);
console.log('hello world ! why this does NOT show in console?!')
return false;
}
render() {
return(
<form method="POST" action="/">
<div onSubmit={this.formSubmitHandler}>
<h1>Select a file to upload</h1>
<input type="file" accept=".txt" name="ctlFileInput"></input>
<p/>
<input type="submit" value="Click to submit" />
</div>
</form>
)
}
}
export default TestSubmitComponent;

Your formSubmitHandler() method isn't actually triggered so the default behavior of a page refresh is occurring on each form submission since the onSubmit() callback needs to be tied to your form element:
<form onSubmit={this.formSubmitHandler}>
Additionally, I would remove the POST request to the / route on your server. This is defined within your form element but this isn't desired since this will make a call to your server, instead of trigger your formSubmitHandler() method. Maybe you could try something along the lines of:
import React from 'react';
class TestSubmitComponent extends React.Component {
constructor(props) {
super(props);
}
formSubmitHandler = (e) => {
e.preventDefault(); //should prevent submit, and continue below?
console.log(e);
console.log('hello world ! why this does NOT show in console?!')
return false;
}
render() {
return(
<form onSubmit={this.formSubmitHandler}>
<div>
<h1>Select a file to upload</h1>
<input type="file" accept=".txt" name="ctlFileInput"></input>
<p/>
<input type="submit" value="Click to submit" />
</div>
</form>
)
}
}
export default TestSubmitComponent;
Hopefully that helps!

onSubmit is written as the attribute of the div element after form therefore it was not working as expected. Page is loading after form submit because form's submit event was uncontrolled.
If you will move it to the form element then it will work.
Example
<form method="POST" action="/" onSubmit={this.formSubmitHandler}>
<div>
<h1>Select a file to upload</h1>
<input type="file" accept=".txt" name="ctlFileInput"></input>
<p/>
<input type="submit" value="Click to submit" />
</div>
</form>

Related

ReactJS On submit change classes of button and input field

I have a form and when I "Submit" the form I want to add an attribute and some extra classes to the "submit" button and the input field
This is my handleSubmit function
handleSubmit = event => {
event.preventDefault();
const formData = new FormData(event.target);
axios.post(`MyPostUrl`,formData)
.then(res => {
})
}
This is my form
<form onSubmit={this.handleSubmit} method="POST">
<div className="form-row">
<input required min="1" max="10" name="grade" className="form-control col-md-5" type="number" />
<button className="btn btn-outline-primary col-md-6">
Grade
</button>
</div>
</form>
So in let's say jQuery i could just go $(this).find("someClass") and do what ever i need to do with it. How can i achieve this with React?
What I'm trying to do is change the input class to col-md-12 and add an disabled attribute and I want to remove the button on submit
And I have a lot of forms since I've mapped over an object
Consider an example like this: https://codesandbox.io/s/throbbing-bird-ob89o
The idea is to use your component-state to control what classes, styles and attributes to use for your markup.
In this case, we define a submitted state and depending on its Boolean-value, we can use ternary operators to toggle the code we want to render.
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
state = {
grade: "",
submitted: false
};
handleSubmit = e => {
e.preventDefault();
this.setState({
submitted: true
});
};
handleOnChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
render() {
const { submitted, grade } = this.state;
return (
<form onSubmit={this.handleSubmit} method="POST">
<div className="form-row">
<input
required
onChange={this.handleOnChange}
min="1"
max="10"
name="grade"
className={`form-control ${submitted ? "col-md-12" : "col-md-5"}`}
value={grade}
type="number"
disabled={submitted}
/>
{!submitted ? (
<button className="btn btn-outline-primary col-md-6">Grade</button>
) : (
""
)}
</div>
</form>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
When you submit the form, we toggle the submitted state to true. Our component re-renders and that recalculates all the ternary operators in our mark-up like ${submitted ? "col-md-12" : "col-md-5"} and etc.
You would have to use react states for managing classes too.
e.g:
<button className={this.state.buttonClass}>
Grade
</button>
Better yet, create a wrapper component around it so that these actions can be controlled via props *e.g disabled={true} would add class

why the page refresh on button click in react?

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

how to remove the class from parent div in keyup using react js

I am having set of form fields, when i click on the submit button i adding error message class for each input textbox parent div this all are working fine,
my problem is when i keyup the textbox i need to remove the error message class using reactjs
<div class="form-blk">
<label class="f-row error-msg">
<input type="text" required />
</label>
</div>
my div structure is like this, for validation i am using npm validator module
So with the limited data provided in the question, this should give you some direction.
Declare a state for the state change on the keyUp:
var state = {
isKeyUp: false,
}
updateKeyUpState() {
this.setState( function( prevState) {
return {
isKeyUp: !prevState.isKeyUp
}
})
}
Your Render function:
render() {
<button type="submit" onkeyup={updateKeyUpState}> SUBMIT </button>
<div class="form-blk">
<label className={this.state.isKeyUp ? 'f-row': 'f-row error-msg'}>
<input type="text" required />
</label>
</div>
}
Try this
function getCompState(){return {keyUp : false}}
class Example extends React.Component{
constructor(props){
super(props)
this.state = getCompState();
}
render(){
var class_new = 'error-msg';
if(this.state.keyUp ){
class_new = 'class_new_defined'
}
return(
<div className="form-blk">
<label className={"f-row "+class_new}>
<input type="text" required />
</label>
</div>
)
}
}
Css
.class_new{}

Cannot trigger component's function in my react app

I am currently working with react and I have runned into a problem this morning that i do not understand.
I am trying to handle a form submit from my component with a function by passing it in the onSubmit property but it does not trigger it. I then added a button to trigger a mock function with its onClick property, and i still got the same problem; it appears than I can't trigger my function and I cannot find any solution on the Google.
Here is my code so you can check it out:
import React from 'react';
import AgentsStore from '../stores/AgentsStore';
import AgentsActions from '../actions/AgentsActions';
class Agents extends React.Component {
constructor(props) {
super(props);
this.state = AgentsStore.getState();
this.onChange = this.onChange.bind(this);
}
componentDidMount() {
AgentsStore.listen(this.onChange);
}
componentWillUnmount() {
AgentsStore.unlisten(this.onChange);
}
onChange(state) {
this.setState(state);
}
handleSubmit(event) {
event.preventDefault();
var user = {};
user.name = this.state.newUser.name.trim();
user.lastname = this.state.newUser.lastname.trim();
if (user.name && user.lastname) {
AgentsActions.createUser(user);
}
}
onClick() {
console.log('clicked');
}
render() {
return (
<div /*className='container'*/>
<div className='alert alert-info'>
Hello from Agents
</div>
<div className='panel panel-default'>
<div className='panel-heading'>Create User</div>
<div className='panel-body'>
<form onSubmit={this.handleSubmit.bind(this)}>
<div className='form-group'>
<label className='control-label'>Name</label>
<input type='text'
className='form-control'
ref='nameTextField'
value={this.state.newUser.name}
onChange={AgentsActions.updateName} />
</div>
<div className='form-group'>
<label className='control-label'>Lastname</label>
<input type='text'
className='form-control'
ref='lastnameTextField'
value={this.state.newUser.lastname}
onChange={AgentsActions.updateLastname} />
</div>
<h4>Address</h4>
<button type='submit' className='btn btn-primary'>Submit</button>
</form>
<button onClick={this.onClick} className='btn btn-primary'>Submit</button>
</div>
</div>
</div>
)
}
}
export default Agents;
I do not know if I am missing something in my code or there is an error but i am kind of desperate. Also I am basing my code on another file that i have which is working just fine...
Thank you in advance for your time

Highly reusable react component without any code change and use only properties

I would like to create a component which I can reuse also for other projects without any code change (only by passing different properties).
A small example:
I have a login form which has a username input and a password input which can look for example like this:
class Login extends Component {
static propTypes = {
login: PropTypes.func.isRequired,
defaultEmailValue: PropTypes.string,
defaultPasswordValue: PropTypes.string,
};
handleSubmit = (event) => {
if (event) {
event.preventDefault();
}
const username = this.refs.username;
const password = this.refs.password;
this.props.login(username.value, password.value);
};
render() {
const {
defaultEmailValue,
defaultPasswordValue,
} = this.props;
return (
<form method="post">
<input defaultValue={defaultEmailValue} ref="username" type="email" />
<input defaultValue={defaultPasswordValue} ref="password" type="password" />
<button onClick={this.handleSubmit} type="submit">Submit</button>
</form>
);
}
}
This is the minimal version of a login form, but what to do when I want to extend the render function to add container components like this (added column tags):
class Login extends Component {
/*....*/
render() {
const {
defaultEmailValue,
defaultPasswordValue,
} = this.props;
return (
<form method="post">
<div class="row">
<div class="col-md-6">
<input defaultValue={defaultEmailValue} ref="username" type="email" />
</div>
<div class="col-md-6">
<input defaultValue={defaultPasswordValue} ref="password" type="password" />
</div>
</div>
<button onClick={this.handleSubmit} type="submit">Submit</button>
</form>
);
}
}
Therefore I have always to modify the render function. Is there a good possibility to do this only with properties?
I estimated to do this with a Wrapper-Component over the Login component but then I have always rewrite the complete render function.
The next possible solution I thought about is to pass wrapper component classes through properties which can be rendered. But is this so a good solution or is this bad practice?
Unfortunately, I found no real solution for this tutorial in the internet and therefore I try it here. Thanks in advance :-)
Is there a good possibility to do this only with properties?
Representational Components are exactly for this kind of things.
export default const LoginForm = (/**props**/ {username, email, submitHandler, errors}) => {
return (
<form>
{/* as usual */}
</form>
)
}
use in your ContainerComponent:
...
render() {
return (
<div className="loginWrapper">
<LoginForm ...this.props ...this.state ...whatever username="pete" />
</div>
)
}
...

Resources