Hello I'm new to react and redux. What I'm trying to do is have an edit page that gets the value from my server and puts it in an input value so the user can edit the value.
<FormGroup>
<Label htmlFor="name">Name *</Label>
<div className="controls">
<InputGroup>
<Input id="name" size="16" type="text" value={this.props.user.name} />
</InputGroup>
</div>
</FormGroup>
Inside a react component.
constructor(props) {
super(props)
this.handleSubmit = this.handleSubmit.bind(this)
this.componentWillMount = this.componentWillMount.bind(this)
}
componentWillMount(){
// this will return my current user
this.props.dispatch(fetchUser())
console.log(this.props.user.name) //outputs 'John'
}
How can i insert the username inside the input. I tried using the id and all the traditional javascript ways but its not working.
It looks like used a react-bootstrap.
Below sample use defaultValue property.
if you want to handle input value by
<FormControl
type="text"
autoFocus
onBlur={this.handleMessage}
defaultValue={this.props.user.name}
/>
handlers...
handleMessage = (event) => {
this.setState({
userName: event.target.value,
});
// or do action
// this.props.dispatch(notifyAction.changeUserName(event.target.value));
};
Related
Hi I'm newbie of react and now I'm starting to learn the basic full-stack concept.
I want to make when User clicked the 'edit' button, the data's in the input text still remained in the text box before user click edit.
but I faced this error
Warning: A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
how can I solve this problem?
thank you in advance!
import React, { Component } from "react";
import axios from "axios";
class Edit extends Component {
constructor(props){
super (props);
this.onChangeName = this.onChangeName.bind(this);
this.onChangePosition = this.onChangePosition.bind(this);
this.onChangePhone = this.onChangePhone.bind(this);
this.onChangePasscode = this.onChangePasscode.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
name:"",
position: "",
phone:"",
passcode: ""
}
}
componentDidMount() {
axios.get('http://localhost:8888/reactJsCRUD/getById.php?id='+this.props.match.params.id)
.then(response => {
this.setState({
name:response.data.employeeName,
postition:response.data.employeePosition,
phone: response.data.employeePhone,
passcode:response.data.passcode
});
})
.catch(function(error) {
console.log(error);
})
}
onChangeName(e) {
this.setState({
name: e.target.value
});
}
onChangePosition(e) {
this.setState({
position: e.target.value
});
}
onChangePhone(e) {
this.setState({
phone:e.target.value
});
}
onChangePasscode(e) {
this.setState({
passcode: e.target.value
});
}
onSubmit(e) {
}
render() {
return (
<div style={{ marginTop: 10 }} className="w-50 p-3">
<h3> Add New Employee</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group-3">
<label>Name: </label>
<input type="text" className="form-control" value={this.state.name} onChange={this.onChangeName} />
</div>
<div className="form-group">
<label htmlFor= "positionFormSelect">Position: </label>
<select className="form-control" id="positionFormSelect" value={this.state.position} onChange={this.onChangePosition}>
<option>Select the position</option>
<option value= "manager">Manager</option>
<option value= "server">Server</option>
<option value= "cook">Cook</option>
</select>
</div>
<div className="form-group">
<label>Phone: </label>
<input type="text" className="form-control" value={this.state.phone} onChange = {this.onChangePhone}/>
</div>
<div className="form-group">
<label>Passcode: </label>
<input type="text" className="form-control" value= {this.state.passcode}onChange = {this.onChangePasscode}/>
</div>
<div className="form-group">
<input
type="submit"
value="Edit Employee"
className="btn btn-primary"
/>
</div>
</form>
</div>
);
}
}
export default Edit;
I think you have a typo here:
<input type="text" className="form-control" value={this.state.posscode} onChange={this.onChangePasscode}/>
value should be this.state.passcode
In your code you are setting the state in componentDidMount and that is why it is showing you a warning.
Because you are using that state for controlled component and if that state get updated from outside of event handler then it will always shows warning as a alert that your state that seems to be used for controlled component, now getting updated outside the scope of controlled component. So advice is that if you want to use state for controlled component, then make sure that specific state do not gets updated from anywhere else.
That's why it is giving you a warning of uncontrolled component because your state is not controlled now as it is getting updated outside of controlled component scope.
Hey guys I got the solution.
The problem was in the PHP file!
<?php
require_once "cors.php";
require_once "connect.php";
cors();
$con = connect();
$id = $_GET['id'];
// Get by id
$sql = "SELECT * FROM employee WHERE employeeId = {$id} LIMIT 1";
$result = mysqli_query($con,$sql);
$row = mysqli_fetch_assoc($result);
print_r($row)
echo $json = json_encode($row);
exit;
because of print_r($row), the got data also had array and that's why I could not access response.data properly in React :) thank you all !
It's a simple form which updates the state object onChange and displays that state object when submitted. I was not able to get it to work when there are multiple input elements.
Can anyone tell me what's wrong in this code?
onSubmit works when there's only one input element, but not when there are multiple!
class ReactForm extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.validate = this.validate.bind(this);
this.state = {
name: "",
email: ""
};
}
handleChange(event) {
event.preventDefault();
const name = event.target.name;
const value = event.target.value;
this.setState({
[name]: value
});
}
validate(event) {
event.preventDefault();
console.log(this.state);
}
render() {
return (
<div>
<form onSubmit={this.validate}>
<div>
<input
type="text"
name="name"
value={this.state.name}
onChange={this.handleChange}
/>
<input
type="email"
name="email"
value={this.state.email}
onChange={this.handleChange}
/>
</div>
</form>
</div>
);
}
}
ReactDOM.render(
<ReactForm />,
document.getElementById("root")
);
You need to have a submit button if you have more than 1 input, you can add a hidden one if you want:
<input type="submit" hidden />
Here's a codesandbox: https://codesandbox.io/s/suspicious-almeida-e3f00
And here is the explanation in detail: Why does a FORM with one text INPUT submit on enter while one with two text INPUTs does not?
I really liked the approach of tudor.
Here is a different approach that can remove the state handling as well. But this may require polyfill for IE and Safari. You can use FormData to access the form values.
new FormData(e.target);
Here is the working sandbox link: https://codesandbox.io/s/long-wind-ybl1w
Hope this helps!
Please add an element input and button. Button should have type="submit" for submitting!
It will work!
Please help me to understand where I am doing what mistake? I created CustomerForm React Component, which having few form fields. These form fields will add records and in another component will show records into table format.
Every thing is working fine for CustomerForm React Component, but if I am adding onSubmit function than form fields are not loading and I am getting console error as:-
Uncaught ReferenceError: onSubmit is not defined
at new CustomerForm (index.js:32590)
<button type="submit" className="btn btn-primary" onClick={ e => this.onSubmit(e)} > Submit </button>
Also please suggest any better way to write ReactJS code using Props & State...
// Let's import react for creating component
import React from "react";
// Create CustomerForm component
class CustomerForm extends React.Component{
// create constructor function for CustomerForm component
constructor(props){
// call super, so constructor function can connect with CustomerForm component
super(props);
// Use state add object with their property and value
this.state = {
firstName : "",
lastName : "",
phoneNo : "",
issue : "",
}
// Create changeData function
// changeData = e => {
// this.setState({
// [e.target.name] : e.target.value
// });
// };
onSubmit = e => {
e.preventDefault();
console.log(this.state);
}
} // close constructor function
render(){
return(
<form>
<div className="form-group">
<label htmlFor="fname">First name</label>
<input
type="text"
className="form-control"
id="fname"
placeholder="First name"
value={this.state.firstName}
onChange={e => this.setState({ firstName: e.target.value })}
/>
{/* call setState for change firstName value
question - I created changeData function which target name attribute and change value for form fields, but it's not working
onChange={e => this.changeData(e)}
*/}
</div>
<div className="form-group">
<label htmlFor="lname">Last name</label>
<input
type="text"
className="form-control"
id="lname"
placeholder="Last name"
value={this.state.lastName}
onChange={e => this.setState({ lastName: e.target.value })}
/>
{/* call setState for change lastName value */}
</div>
<div className="form-group">
<label htmlFor="phone">Phone no.</label>
<input
type="text"
className="form-control"
id="phone"
placeholder="Phone no."
value={this.state.phoneNo}
onChange={e => this.setState({phoneNo: e.target.value})}
/>
{/* call setState for change phoneNo value */}
</div>
<div className="form-group">
<label htmlFor="issue">Issue</label>
<textarea
className="form-control"
id="issue"
rows="3"
value={this.state.issue}
onChange={e => this.setState({issue: e.target.value})}
>
{/* call setState for change issue value */}
</textarea>
</div>
<button
type="submit"
className="btn btn-primary"
onClick={ e => this.onSubmit(e)}
>
Submit
</button>
</form>
);
}
}
export default CustomerForm;
You're declaring a variable named onSubmit on the constructor and trying to access it with this.onSubmit, like a property.
You can do this in your constructor:
this.onSubmit = e => {
e.preventDefault();
console.log(this.state);
}
The suggestion
A better way to accomplish this is extracting your onSubmit method to a class method, with makes your code more readable and more consistent. Would be something like this:
// Let's import react for creating component
import React from "react";
// Create CustomerForm component
class CustomerForm extends React.Component{
// create constructor function for CustomerForm component
constructor(props){
// call super, so constructor function can connect with CustomerForm component
super(props);
// Use state add object with their property and value
this.state = {
firstName : "",
lastName : "",
phoneNo : "",
issue : "",
}
}
/////////
/// Your submit handler is now a method in the CustomerForm class,
/// so you can access with the keyword "this"
onSubmit(e) {
e.preventDefault();
console.log(this.state);
}
render(){
return(
<form onSubmit={e => this.onSubmit(e)}>
{/* Note that I've changed your handler to form,
is usually better than put on a button, since you're using a form already */}
<div className="form-group">
<label htmlFor="fname">First name</label>
<input
type="text"
className="form-control"
id="fname"
placeholder="First name"
value={this.state.firstName}
onChange={e => this.setState({ firstName: e.target.value })}
/>
{/* call setState for change firstName value
question - I created changeData function which target name attribute and change value for form fields, but it's not working
onChange={e => this.changeData(e)}
*/}
</div>
<div className="form-group">
<label htmlFor="lname">Last name</label>
<input
type="text"
className="form-control"
id="lname"
placeholder="Last name"
value={this.state.lastName}
onChange={e => this.setState({ lastName: e.target.value })}
/>
{/* call setState for change lastName value */}
</div>
<div className="form-group">
<label htmlFor="phone">Phone no.</label>
<input
type="text"
className="form-control"
id="phone"
placeholder="Phone no."
value={this.state.phoneNo}
onChange={e => this.setState({phoneNo: e.target.value})}
/>
{/* call setState for change phoneNo value */}
</div>
<div className="form-group">
<label htmlFor="issue">Issue</label>
<textarea
className="form-control"
id="issue"
rows="3"
value={this.state.issue}
onChange={e => this.setState({issue: e.target.value})}
>
{/* call setState for change issue value */}
</textarea>
</div>
<button
type="submit"
className="btn btn-primary"
>
Submit
</button>
</form>
);
}
}
export default CustomerForm;
Controlled Components
Just one more thing I think it may be helpful to you (I've noted your comment about changeData) so if you not resolve the way to do controlled inputs, this minimalist example may help you, with a onChangeHandler I usually use:
import React from 'react';
export default class MyControlledComponent extends React.Component {
constructor(props){
super(props);
// Initiating the first value for our controlled component
this.state = {
name: ""
}
}
submitHandler(e) {
e.preventDefault();
console.log('Hi, ' + this.state.name + '!');
}
onChangeHandler(e) {
const { name, value } = e.target
/*
Here we using the name property of your input to
increase reuse of this function
*/
this.setState({
[name]: value
});
}
render(){
return (
<div className="my-app">
<form onSubmit={e => this.submitHandler(e)}>
<input type="text"
name="name"
value={this.state.name}
onChange={e => this.onChangeHandler(e)} />
<button>Send!</button>
</form>
</div>
)
}
}
Hope it helps!
Your onSubmit function is not bind either bind it in constructor or use fat arrow properly like
{(return)=>{functionname()}}
I am new to react js.
I have several inputs in my form and considering controllable input approach in React , I am trying to do the job with one event handler to every other inputs. I took some references in stack overflow and come to this. Still not able to figure it out why I am unable to write inside my input box.
Here is my code.
import React, {Component} from 'react';
import { Grid, Row, Col , Button } from 'react-bootstrap';
class ContactForm extends Component {
constructor(props) {
super(props);
this.state = {
name: '' ,
email: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({[e.target.name]: e.target.value})
}
render() {
return (
<form>
<input name="input1" value={this.state.name} onChange={this.handleChange}/>
<input name="input2" value={this.state.email} onChange={this.handleChange} />
<p>{this.state.name}, {this.state.email}</p>
</form>
);
}
}
export default ContactForm;
You're using the name attribute to identify the input, but you're reading the wrong values in the render function, "name" and "email" instead of "input1" and "input2"
You can do this instead:
<input name="input1" value={this.state.input1} onChange={this.handleChange}/>
<input name="input2" value={this.state.input2} onChange={this.handleChange} />
or
<input name="name" value={this.state.name} onChange={this.handleChange}/>
<input name="email" value={this.state.email} onChange={this.handleChange} />
You'd also have to change this :
this.state = {
name: '' ,
email: ''
};
in the constructor if you're using the first option.
I would use ref to achieve this:
handleChange(e) {
const {input1, input2} = this.refs;
//do what ever you want with the values
}
render() {
return (
<form>
<input name="input1" value={this.state.name} ref="input1" />
<input name="input2" value={this.state.email} ref="input2" onChange={this.handleChange} />
<p>{this.state.name}, {this.state.email}</p>
</form>
);
}
}
Also, I would use a submit button, or something like that, instead of an event listener on one or two of the inputs
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