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
Related
I have a very simple component with a single state, I initialize the state when component is created and try to change it when a form is submitted.
It doesn't work for some reason.
import React, { Component } from "react";
export default class AddTodo extends Component {
constructor() {
super();
this.state = {
submited: false
};
}
handleSubmit = event => {
this.setState = {
submited: true
};
alert("Submited state: " + this.state.submited);
event.preventDefault();
};
render() {
return (
<div className="container mt-3">
<form onSubmit={this.handleSubmit}>
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="New Todo Description Here"
/>
<div className="input-group-append">
<button className="btn btn-primary" type="submit">
Add Todo
</button>
</div>
</div>
</form>
</div>
);
}
}
this.setState is a function, so call it like one using brackets ().
this.setState({
submited: true
});
import React, { Component } from "react";
export default class AddTodo extends Component {
constructor() {
super();
this.state = {
submited: false
};
}
handleSubmit = event => {
this.setState({
submited: true
},()=>{
alert("Submited state: " + this.state.submited);
event.preventDefault();
});
};
render() {
return (
<div className="container mt-3">
<form onSubmit={this.handleSubmit}>
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="New Todo Description Here"
/>
<div className="input-group-append">
<button className="btn btn-primary" type="submit">
Add Todo
</button>
</div>
</div>
</form>
</div>
);
}
}
As you can see here setState is a function, but you're assigning a value to it.
The problem is here:
this.setState = {
submited: true
};
It should be:
this.setState({submitted: true}); // Mind the typo also
Just to make a quick note, the React team published react hooks in version 16.8 as a replacement to class components that have some drawbacks. I would give it a try, the docs are here.
With hooks your code would look like this:
import React, { useState } from 'react';
function AddTodo() {
// Declare a new state variable, which we'll call "count"
const [isSubmitted, setSubmission] = useState(false);
function handleSubmit(event) {
setSubmission(true);
event.preventDefault();
}
return (
<div className="container mt-3">
<form onSubmit={handleSubmit}>
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="New Todo Description Here"
/>
<div className="input-group-append">
<button className="btn btn-primary" type="submit">
Add Todo
</button>
</div>
</div>
</form>
);
}
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>
I am creating edit form.First i have to get data to edit form and i am calling it in componentDidMount().Please see code below.
import React from 'react';
import CompanyForm from './CompanyForm';
import { connect } from 'react-redux';
import { companyActions } from '../../../redux/actions/company-action';
class EditCompanyPage extends React.Component {
constructor(props){
super(props);
};
componentDidMount () {
const { id } = this.props.match.params
const { dispatch } = this.props;
dispatch(companyActions.getCompany(id));
}
render(){
const {editUser } = this.props;
return(
<div>
<h1>Edit Company</h1>
{
editUser && <CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />
}
</div>
);
};
}
function mapStateToProps(state) {
const { editUser } = state.companyReducer;
return {
editUser
};
}
const EditCompany = connect(mapStateToProps)(EditCompanyPage);
export default EditCompany;
see code for CompanyForm component below:
import React from 'react';
class CompanyForm extends React.Component {
constructor(props){
super(props);
this.state = {
company :{
name : this.props.companyDataFP.name || '',
address1 : this.props.companyDataFP.address1 || '',
}
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
handleChange(e) {
const { name, value } = e.target;
const newState = Object.assign({}, this.state);
newState.company[name] = value;
this.setState(newState);
}
handleSubmit(e) {
e.preventDefault();
return false;
}
render(){
return(
<div className="col-md-12">
<form onSubmit={this.handleSubmit}>
<div className="row">
<div className="col-md-6">
<div className='form-group'>
<label htmlFor="name">Name</label>
<input type="text" name="name" className="form-control" onChange={this.handleChange} value={this.state.company.name} />
</div>
</div>
<div className="col-md-6">
<div className='form-group'>
<label htmlFor="address1">Address 1</label>
<input type="text" name="address1" className="form-control" onChange={this.handleChange} value={this.state.company.address1} />
</div>
</div>
</div>
<div className="row">
<div className="col-md-12">
<div className='form-group'>
<input type="submit" className="btn btn-info" value="submit" />
</div>
</div>
</div>
</form>
</div>
);
};
}
export default CompanyForm;
It works fine when i access this form with
<Link to="/edit-form/:id" >Edit</Link>
but when i refresh the current page then values are not rendering into form to edit.
I am using redux approach for state management, please guide me i am new to react.
Probably ComponyForm initializes form on its componentDidMount lifecycle function, so when editUser arrives nothing will change.
A way to handle this is changing:
<CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />
to:
{editUser.name && <CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />}
I am new to ReactJS and trying to build a sample application
I am unable to get enter the value in textbox and unable to get the value in alert. Am I doing something wrong. I have tried the example given on React.Js Form, but not working.
import React, { Component } from "react";
class AddNewStudent extends Component {
constructor(props) {
super(props);
this.state = {value:''};
this.OnSubmit = this.OnSubmit.bind(this);
}
OnSubmit(event){
alert('name value is : '+this.state.value);
event.preventDefault();
}
render(){
return(
<div>
<form onSubmit={this.OnSubmit}>
<fieldset className="Student-Form" id={this.props.id}>
<legend className="Legend">Add mew student</legend>
<div>
<div className="Block">
<div className="Float-Left">
<label>
<span>Name : </span>
<input type="text" value={this.state.value} />
</label>
</div>
</div>
<div className="clearFix" />
<div className="Block">
<div className="Float-None">
<label>
<input type="submit" value="Save" />
</label>
</div>
</div>
</div>
</fieldset>
</form>
</div>
);
}
}
export default AddNewStudent;
please change :
<input type="text" value={this.state.value} />
to:
<input type="text" value={this.state.value} onChange = {this.onChange}/>
In your class, add the 'onChange' function:
onChange(e){
this.setState({
value: e.target.value
})
}
and in your constructor:
this.onChange = this.onChange.bind(this)
Edit 1:
please check my codepen here
Edit 2:
If you have too many inputs, you can use a function like this:(it's just a rough example, in real world I'll create a new component to handle this together)
//in your constructor
this.state = {}
//in class 'controlled component way'
createInput(num){
let inputArray = []
for(let i = 0; i < num; i ++){
inputArray.push(<input key = {i} name = {i} onChange = {this.onChange} value = {this.state[i] || ''} />)
}
return inputArray
}
onChange(e){
let key = e.target.name
let newState = {}
newState[key] = e.target.value
this.setState(newState)
}
// in your render function
return <div>
{this.createInput(100)}
</div>
check my codepen here for this example
and of course you can also do this using uncontrolled component.
controlled component and uncontrolled
You can either bind onChange event to your input or setState when submiting the value , you cant change the state like that
Change your code to something like this
import React, { Component } from "react";
class AddNewStudent extends Component {
constructor(props) {
super(props);
this.state = {value:''};
this.OnSubmit = this.OnSubmit.bind(this);
}
OnSubmit(event){
this.setState({value: this.refs.infield.value},()=>{
alert('name value is : '+this.state.value);
})
event.preventDefault();
}
render(){
return(
<div>
<form onSubmit={this.OnSubmit}>
<fieldset className="Student-Form" id={this.props.id}>
<legend className="Legend">Add mew student</legend>
<div>
<div className="Block">
<div className="Float-Left">
<label>
<span>Name : </span>
<input type="text" ref = "infield"/>
</label>
</div>
</div>
<div className="clearFix" />
<div className="Block">
<div className="Float-None">
<label>
<input type="submit" value="Save" />
</label>
</div>
</div>
</div>
</fieldset>
</form>
</div>
);
}
}
export default AddNewStudent;
Hi to get the value add a name to the input and an onChange function to set the value to the state and then do what evere you want in onsubmit function
I cant write you a working code now because I'm using my phone but my this Will help
onfieldchange(e) {
this.setState({[e.target.name]: e.target.value});
}
onaSubmit(){
//do your code here
}
....
....
<input type="text" name="firstName" value={this.state.firstName} />
Hope this help you
There are two ways to handle form elements in reactjs:
Controlled and uncontrolled components(using refs).In controlled component approach ,you have to add the state of the input field to the input field value and onChange event to it, which is the one you are trying to do.Here is the working code.
import React, { Component } from "react";
class AddNewStudent extends Component {
constructor(props) {
super(props);
this.state = {
firstname:''
};
this.OnSubmit = this.OnSubmit.bind(this);
this.OnChange = this.OnChange.bind(this);
}
OnSubmit(event){
alert('name value is : '+this.state.firstname);
event.preventDefault();
}
OnChange(){
this.setState({
[e.target.name] : [e.target.value]
});
}
render(){
return(
<div>
<form onSubmit={this.OnSubmit}>
<fieldset className="Student-Form" id={this.props.id}>
<legend className="Legend">Add mew student</legend>
<div>
<div className="Block">
<div className="Float-Left">
<label>
<span>Name : </span>
<input type="text"
name="firstname"
value={this.state.firstname}
OnChange={this.OnChange}
/>
</label>
</div>
</div>
<div className="clearFix" />
<div className="Block">
<div className="Float-None">
<label>
<input type="submit" value="Save" />
</label>
</div>
</div>
</div>
</fieldset>
</form>
</div>
);
}
}
export default AddNewStudent;
new react user here.
i am trying to access form data in my parent app from the child form. I am trying to alert or console the data from the parent so I can visually see what was typed in the form. Once I can access the data in the parent I will try and move it to my list array.
PARENT
class App extends Component {
constructor() {
super();
this.state = {
lists: [],
items: {}
};
}
handleAddList(s) {
alert('I am calling function from child')
console.log(this.refs.id.value) // this errors out on me
}
render() {
return (
<div className="App">
<AddList addList={this.handleAddList.bind(this)} />
<div id="listsDiv" className="List">
<Lists lists={this.state.lists} items={this.state.items} addItem {this.handleAddItem.bind(this)} />
</div>
</div>
);
}
}
CHILD
class AddList extends Component {
handleSubmit(e) {
e.preventDefault();
alert(this.refs.id.value)
this.props.addList()
}
render() {
return (
<div id="addListDiv">
<form onSubmit={this.handleSubmit.bind(this)}>
<div id='addList'>
<label>What will be on your next list?
<input type='text' ref='id' id='newID'></input>
</label>
</div><br />
<input type='submit' value='Create List' />
</form>
</div>
);
}
}
You should set the ref on the input using a callback, like this:
<input type='text' ref={input => { this.input = input; }} id='newID'></input>
Then access it in your event handler like this:
alert(this.input.value);
However, if you are new to React, you should try using controlled components before you try to use refs.
https://reactjs.org/docs/forms.html
CHILD
import ReactDOM from 'react-dom';
class AddList extends Component {
handleSubmit(e) {
e.preventDefault();
var day = ReactDOM.findDOMNode(this.refs.id).value.trim();
this.props.addList(day);
}
render() {
return (
<div id="addListDiv">
<form onSubmit={this.handleSubmit.bind(this)}>
<div id='addList'>
<label>What will be on your next list?
<input type='text' ref='id' id='newID'></input>
</label>
</div><br />
<input type='submit' value='Create List' />
</form>
</div>
);
}
}
PARENT
class App extends Component {
handleAddList(args) {
console.log(args);
}
render() {
return (
<div className="App">
<AddList addList={this.handleAddList.bind(this)} />
</div>
);
}
}
Edit it a little to work for you.