Updating/editing username in dropdown list in react - reactjs

Can anyone help me.I have been trying to learn react for while now. How do I edit/update username in react dropdown list. Lets say there is a misspelled username in the dropdown list. If I want to change or edit that username how can I do that in react. I can update everything else, except the username. Here is my code..
import React, {Component} from 'react';
import axios from 'axios';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css'
class EditExercise extends Component {
constructor(props){
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangeDescription = this.onChangeDescription.bind(this);
this.onChangeDuration = this.onChangeDuration.bind(this);
this.onChangeDate = this.onChangeDate.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.select = React.createRef();
this.state = {
username:'',
description : '',
duration: 0,
date:new Date(),
users: []
}
}
componentDidMount(){
axios.get('http://localhost:5000/exercises/'+this.props.match.params.id)
.then(responce => {
this.setState({
username: responce.data.username,
description: responce.data.description,
duration:responce.data.duration,
date: new Date(responce.data.date)
})
})
.catch((error) =>{
console.log(error)
})
axios.get('http://localhost:5000/exercises/')
.then(responce => {
if(responce.data.length > 0){
this.setState({
users: responce.data.map(user =>user.username),
});
}
})
}
onChangeUsername(e){
this.setState({
username: e.target.value
});
}
onChangeDescription(e){
this.setState({
description: e.target.value
});
}
onChangeDuration(e){
this.setState({
duration: e.target.value
});
}
onChangeDate(date){
this.setState({
date: date
})
}
onSubmit(e){
e.preventDefault();
const exercise = {
username : this.state.username,
description: this.state.description,
duration: this.state.duration,
date: this.state.date
}
console.log(exercise);
axios.post('http://localhost:5000/exercises/update/'+this.props.match.params.id, exercise)
.then(res => console.log(res.data));
window.location ='/';
}
render() {
return (
<div>
<h3>Edit Exercise Log</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select ref={this.select}
required
className="form-control"
value={this.state.username}
onChange={this.onChangeUsername}>
{
this.state.users.map((user) => {
return <option
key={user}
value={user}>{user}
</option>
})
}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input type="text"
required
className="form-control"
value={this.state.description}
onChange={this.onChangeDescription}
/>
</div>
<div className="form-group">
<label>Duration (in minutes): </label>
<input type="text"
className="form-control"
value={this.state.duration}
onChange={this.onChangeDuration}
/>
</div>
<div className="form-group">
<label>Date: </label>
<div>
<DatePicker
selected={this.state.date}
onChange={this.onChangeDate}
/>
</div>
</div>
<div className="form-group">
<input type="submit" value="Edit Exercise Log" className="btn btn-primary" />
</div>
</form>
</div>
);
}
}
export default EditExercise;

First, I see that you have a dropdown list of users that is coming from an API call. I am not entirely sure what you mean by edit the name. If the names are coming from an API and you want a user to select from a list of usernames you would need to add another JSX Input component with type text just like you do with your other fields.
My suggestion would be to add an edit icon next to the dropdown menu that onClick will setState={editUsername: true, editableUserName: this.state.username}.
This will trigger a ternary operator that renders your new component to the page (see below) below the current username Dropdown menu:
Example:
{ this.state.editUsername ?
<div className="form-group">
<label>Edit Username: </label>
<input type="text"
required
className="form-control"
value={this.state.editableUserName}
onChange={this.onUpdateUsername}
/>
<button onClick="updateUsernameInDB()">
Save Username
</button>
</div>
: null
}
onUpdateUsername will need to update another state variable called editableUserName. Then when the user clicks save call the API that can edit the username of the user. One issue here is you will need some unique identifier for your username that you are updating or you can take the easier approach by sending the original username and the new username and update it that way although that is not the most sustainable over time. Then, when the API to update the username returns 200 you should setState={editUsername: false, updatedUsername: ''}
I hope this helps.

Related

How do I fix a component is changing from controlled input of the type text to be uncontrolled. Reactjs Error [duplicate]

This question already has answers here:
A component is changing an uncontrolled input of type text to be controlled error in ReactJS
(27 answers)
Closed 3 years ago.
I have set the initial state to blanks than why am I encountering this error ? What should I change next ?
I am fetching users from the database using ID and then trying to update their value. I get this error for the first attempt only. subsequent attempts works perfectly.
could there be problem with the backend ?
import React, { Component } from 'react';
import axios from 'axios';
export default class EditUsers extends Component {
constructor(props)
{
super(props);
this.onchangeUsername = this.onchangeUsername.bind(this);
this.onchangeAddress = this.onchangeAddress.bind(this);
this.onchangePhoneno = this.onchangePhoneno.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username:'',
address:'',
phoneno:''
}
}
componentDidMount() {
axios.get('http://localhost:5000/users/'+this.props.match.params.id)
.then(response=>{
this.setState({
username:response.data.username,
address:response.data.address,
phoneno:response.data.phoneno,
})
})
.catch(function (error) {
console.log(error);
})
}
onchangeUsername(e)
{
this.setState({
username:e.target.value
});
}
onchangeAddress(e)
{
this.setState({
address:e.target.value
});
}
onchangePhoneno(e)
{
this.setState({
phoneno:e.target.value
});
}
onSubmit(e){
e.preventDefault();
const user =
{
username:this.state.username,
address:this.state.address,
phoneno:this.state.phoneno
}
console.log(user);
axios.post('http://localhost:5000/users/update/'+this.props.match.params.id,user)
.then(res=>console.log(res.data));
this.setState({
username:this.props.username,
address:this.props.address,
phoneno:this.props.phoneno
})
}
render()
{
return (
<div>
<h3>Edit User List</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<input type="text" required
className="form-control"
value={this.state.username}
onChange={this.onchangeUsername}
/>
</div>
<div className="form-group">
<label>Address: </label>
<input type="text" required
className="form-control"
value={this.state.address}
onChange={this.onchangeAddress}
/>
</div>
<div className="form-group">
<label>Phoneno: </label>
<input type="text" required
className="form-control"
value={this.state.phoneno}
onChange={this.onchangePhoneno}
/>
</div>
<div className="form-group">
<input type="submit" value="Update" className="btn btn-primary" />
</div>
</form>
</div>
);
}
}
Prevent your input value to be null.
If you pass from null to not null, you will recieve this error.
A quick fix could be to do this:
<input
type="text"
required
className="form-control"
value={this.state.username || ''}
onChange={this.onchangeUsername}
/>

Can't input data into form field React

Hi I am making a form can someone please tell me why i cannot seem to enter text in the input fields. I did the type "text" and i thought that usually takes care of that. Any insight would be 100% appreciated.
import React, {Component} from 'react';
class CreateExercise extends Component{
constructor(){
super()
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username:'',
description: '',
duration: 0,
users: []
}
}
componentDidMount() {
this.setState({
users: ['test user'],
username: 'test user'
})
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onChangeUsername(e) {
this.setState({
description: e.target.value
});
}
onChangeUsername(e) {
this.setState({
duration: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
const exercise = ({
username: this.state.username,
description: this.state.description,
duration: this.state.duration
})
console.log(exercise)
window.location = '/';
}
render(){
return(
<div>
<h3>Create New Exercise Log</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select ref="userInput"
required
className="form-control"
value={this.state.username}
onChange={this.onChangeUsername}>
{
this.state.users.map(function(user) {
return <option
key={user}
value={user}>{user}
</option>
})
}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input type="text"
required
className="form-control"
value={this.state.description}
onChange={this.onChangeDescription}
/>
</div>
<div className="form-group">
<label>Duration (in minutes)</label>
<input
type="text"
className="form-control"
value={this.state.duration}
onChange={this.onChangeDuration}
/>
</div>
<div className="form-group">
<input type="submit" value="Create Exercise Log" className="btn btn-primary"/>
</div>
</form>
</div>
)
}
}
export default CreateExercise;
dont use {this.state} in your value fields. Theres no need for it.
also you have 3
onChangeUsername(e) {
im guessing you might want to update the other two methods
It seems like you have some missing handlers and bindings. For example, if you add the event handler onChangeDuration:
onChangeDuration(e) {
this.setState({
duration: e.target.value
});
}
and also do the binding inside the constructor method like:
this.onChangeDuration = this.onChangeDuration.bind(this);
Your duration field should be working.
You can apply the same logic to the description field as well.
Also do not forget to remove the unnecessary onChangeUsername methods. Hope that helps.

axios put request in react is returning empty

I'm pretty new with React and Call requests. I'm building a full stack app using React, express, MySql, and Sequelize.
Everything works fine except for the Put request to edit the client information. I'm using Axios to make those calls and I can add, see, and delete data from the app but the edit part is not working.
When hitting the submit button on the form, the Put request is returning an empty array instead of the actual modified data. My routes are Ok (I believe), as testing it with Postman work just fine. I'm almost sure that my problem is on the method being used in the axios call, but I can't just find the right way to make it work. Any help would be highly appreciated.
import React, { Component } from 'react';
import axios from 'axios';
import API from '../../utils/API';
class index extends Component {
constructor(props) {
super(props);
this.onChangeLastName = this.onChangeLastName.bind(this);
this.onChangeFirstName = this.onChangeFirstName.bind(this);
this.onChangePhone = this.onChangePhone.bind(this);
this.onChangePetName = this.onChangePetName.bind(this);
this.onChangeBreed = this.onChangeBreed.bind(this);
this.onChangeNotes = this.onChangeNotes.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
client: null
}
}
componentDidMount() {
let id = this.props.match.params.id
API.getClient(id)
.then(res => {
this.setState({
client: res.data
})
console.log(this.state.client.id)
})
.catch(error => console.log(error))
}
onChangeLastName(e) {
this.setState({
lastName: e.target.value
});
}
onChangeFirstName(e) {
this.setState({
firstName: e.target.value
});
}
onChangePhone(e) {
this.setState({
phone: e.target.value
});
}
onChangePetName(e) {
this.setState({
petName: e.target.value
});
}
onChangeBreed(e) {
this.setState({
breed: e.target.value
});
}
onChangeNotes(e) {
this.setState({
notes: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
let obj = {
lastName: this.state.client.lastName.value,
firstName: this.state.client.firstName.value,
phone: this.state.client.phone.value,
petName: this.state.client.petName.value,
breed: this.state.client.breed.value,
notes: this.state.client.notes.value
};
let id = this.state.client.id
axios.put("http://localhost:3000/api/clients/" + id, obj)
// .then(alert("client Updated"))
.then(res => console.log(res))
.catch(error => console.log(error))
this.props.history.push('/admin');
}
render() {
const client = this.state.client ? (
<div className="client">
<h3 style={{ marginLeft: "60px" }}>Update Client</h3>
<form onSubmit={this.onSubmit} style={{ padding: "60px" }}>
<div className="form-group">
<label>Last Name: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.lastName}
onChange={this.onChangeLastName}
/>
</div>
<div className="form-group">
<label>First Name: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.firstName}
onChange={this.onChangeFirstName}
/>
</div>
<div className="form-group">
<label>Phone: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.phone}
onChange={this.onChangePhone}
/>
</div>
<div className="form-group">
<label>Pet Name: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.petName}
onChange={this.onChangePetName}
/>
</div>
<div className="form-group">
<label>Breed: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.breed}
onChange={this.onChangeBreed}
/>
</div>
<div className="form-group">
<label>Notes: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.notes}
onChange={this.onChangeNotes}
/>
</div>
<br />
<div className="form-group">
<input type="submit" value="Update Client"
className="btn btn-primary" />
</div>
</form>
</div>
) : (
<div className="center">Loading Client</div>
)
return (
<div className="container">
{client}
</div>
)
}
}
export default index;
I am assuming it is because of the way you are handling the onchange of your inputs. You want to set the onchange to the client value in your state. But instead you are setting it to the state itself. So then when you are building your object to send to the backend you are sending null data because you haven't set any data to the actual client value in your state and it is still null. Try console logging the state and you will see what I'm talking about. Also you are adding a .value to the end each of the state values you are trying to build your object with and this is not necessary. Finally you don't need to specify an onchange for each input just give the input a name attribute and you can set your onchange handler like so:
onChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
so your component would look something like the following:
import React, { Component } from 'react';
import axios from 'axios';
import API from '../../utils/API';
class index extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
client: null
}
}
componentDidMount() {
let id = this.props.match.params.id
API.getClient(id)
.then(res => {
this.setState({
client: res.data
})
console.log(this.state.client.id)
})
.catch(error => console.log(error))
}
onChange(e) {
this.setState({
client: {
...this.state.client,
[e.target.name]: e.target.value
}
});
}
onSubmit(e) {
e.preventDefault();
let obj = {
lastName: this.state.client.lastName,
firstName: this.state.client.firstName,
phone: this.state.client.phone,
petName: this.state.client.petName,
breed: this.state.client.breed,
notes: this.state.client.notes
};
let id = this.state.client.id
axios.put("http://localhost:3000/api/clients/" + id, obj)
// .then(alert("client Updated"))
.then(res => console.log(res))
.catch(error => console.log(error))
this.props.history.push('/admin');
}
render() {
const client = this.state.client ? (
<div className="client">
<h3 style={{ marginLeft: "60px" }}>Update Client</h3>
<form onSubmit={this.onSubmit} style={{ padding: "60px" }}>
<div className="form-group">
<label>Last Name: </label>
<input type="text"
name="lastName"
className="form-control"
defaultValue={this.state.client.lastName}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>First Name: </label>
<input type="text"
name="firstName"
className="form-control"
defaultValue={this.state.client.firstName}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>Phone: </label>
<input type="text"
name="phone"
className="form-control"
defaultValue={this.state.client.phone}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>Pet Name: </label>
<input type="text"
name="petName"
className="form-control"
defaultValue={this.state.client.petName}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>Breed: </label>
<input type="text"
name="breed"
className="form-control"
defaultValue={this.state.client.breed}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>Notes: </label>
<input type="text"
name="notes"
className="form-control"
defaultValue={this.state.client.notes}
onChange={this.onChange}
/>
</div>
<br />
<div className="form-group">
<input type="submit" value="Update Client"
className="btn btn-primary" />
</div>
</form>
</div>
) : (
<div className="center">Loading Client</div>
)
return (
<div className="container">
{client}
</div>
)
}
}
export default index;
It could be because you're calling this.props.history.push immediately after calling axios.post, essentially redirecting before the POST request has a chance to return a response.
Try putting this.props.history.push('/admin') inside the .then().
You are doing multiple thing wrong here,
For every input you should have only 1 onChange handler, every input have name attribute to work with state. For example,
<input type="text"
className="form-control"
defaultValue={this.state.client.lastName}
name="lastName" //Like this should add name for every input like below
onChange={this.onChangeHandler} //This is a common onChangeHandler for every input should add in every input like below
/>
<input type="text"
className="form-control"
defaultValue={this.state.client.firstName}
name="firstName"
onChange={this.onChangeHandler}
/>
And onChangeHandler function should be,
onChangeHandler(e){
this.setState({
...this.state.client,
[e.target.name]:e.target.value
})
}
And finally your onSubmit function should be,
onSubmit(e) {
e.preventDefault();
let obj = {
lastName: this.state.client.lastName, //Remove `.value` as we are getting values from state and not directly from input
firstName: this.state.client.firstName,
phone: this.state.client.phone,
petName: this.state.client.petName,
breed: this.state.client.breed,
notes: this.state.client.notes
};
let id = this.state.client.id
axios.put("http://localhost:3000/api/clients/" + id, obj)
// .then(alert("client Updated"))
.then(res => console.log(res))
.catch(error => console.log(error))
this.props.history.push('/admin');
}
Note: You won't get value here in console.log,
API.getClient(id)
.then(res => {
this.setState({
client: res.data
})
console.log(this.state.client.id)
})
beacuse seState is async, you should use callback in setState to make console.log,
API.getClient(id)
.then(res => {
this.setState({
client: res.data
}, () => console.log(this.state.client.id)) //This is callback
})

How can I view data after fetching the data on the console log in api?

I'm starting to learn reactjs and I want to view the data on the table after I input text on the input fields and show the data on a console log. How can I show all the data input to the page?
onAdd(employee_name, employee_age, employee_salary){
console.log(employee_name, employee_age, employee_salary);}
I expect to show the data input in the input fields in the page. Thank you
This should work:
import React, { Component } from 'react';
class EmployeeInput extends Component {
state = {
employee_name: '',
employee_age: '',
employee_salary: '',
};
handleChange = e => {
const { name, value } = e.target;
this.setState({ [name]: value });
};
render() {
return (
<form>
<div>
<label>
employee_name
<input name="employee_name" type="text" onChange={this.handleChange} />
</label>
Value: {this.state.employee_name}
</div>
<div>
<label>
employee_age
<input name="employee_age" type="text" onChange={this.handleChange} />
</label>
Value: {this.state.employee_age}
</div>
<div>
<label>
employee_salary
<input name="employee_salary" type="text" onChange={this.handleChange} />
Value: {this.state.employee_salary}
</label>
</div>
</form>
);
}
}
Here's a running example: https://stackblitz.com/edit/react-jl2skw?file=index.js

Laravel React MySQL Routing Issue

I am trying to make it so that I can register a user but I am getting a 404 error, assuming that means that react is unable to find the route established by the api.php file, is there anything else that I am missing? I have already set it in the package.json file that the proxy is set to "localhost:8000" (the port I chose to use for laravel's backend stuff). I am confused on why it's not hitting this route upon submitting. I feel like I'm close but I am new to using php as the backend so any insight would be helpful.
I am also creating something where the user is able to play music on the app, so there is a route for that labeled "shop", and that does not work for the sole reason that I have not set that route up (also gives a 404 error).
Below are my api routes that I am trying to get react to detect
<?php
Route::post('register','UserController#register');
Route::post('login','UserController#login');
Route::post('profile','UserController#getAuthenticatedUser');
Route::middleware('auth:api')->get('/user', function(Request $request){
return $request->user();
});
?>
And this is the React portion of my registration file.
import React, { Component } from 'react';
import { register } from './UserFunctions';
class Register extends Component {
constructor() {
super()
this.state = {
first_name: '',
last_name: '',
email: '',
password: '',
errors: {},
}
this.onChange = this.onChange.bind(this)
this.onSubmit = this.onSubmit.bind(this)
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value })
}
onSubmit(e) {
e.preventDefault()
const newUser = {
name: this.state.first_name + ' ' + this.state.last_name,
email: this.state.email,
password: this.state.password
}
register(newUser).then(res => {
if (res) {
this.props.history.push('/login')
}
})
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6 mt-5 mx auto">
<form noValidate onSubmit={this.onSubmit}>
<h1 className="h3 mb-3 font-wieght-normal">
Register
</h1>
<div className="form-group">
<label htmlFor="first_name">First Name</label>
<input type="text" className="form-control" name="first_name" placeholder="Enter First Name" value={this.state.first_name} onChange={this.onChange} />
<label htmlFor="last_name">Last Name</label>
<input type="text" className="form-control" name="last_name" placeholder="Enter Last Name" value={this.state.last_name} onChange={this.onChange} />
<label htmlFor="email">Email Address</label><br />
<input type="email" className="form-control" name="email" placeholder="Enter Email" value={this.state.email} onChange={this.onChange} />
<br />
<label htmlFor="password">Desired Password</label><br />
<input type="password" className="form-control" name="password" placeholder="Enter Password" value={this.state.password} onChange={this.onChange} />
</div>
<button type="submit" className="btn btn-lg btn-primary btn-block">Register</button>
</form>
</div>
</div>
</div>
)
}
}
export default Register
I have those post routes defined, but when I press submit within my register form, I get a 404 error saying that it can't find this route.
Can you show me your
import { register } from './UserFunctions';
file so that I can see the url path defined.
Assuming this route is inside your routes/api.php
Route::group(['middleware' => 'api', 'prefix' => 'v1'], function(){
Route::post('register', 'RegisterController#index');
});
and in JS file
import axios from 'axios'
export const register = newUser => {
return axios
.post('api/v1/register', newUser,
{
headers: { 'Content-Type': 'application/json' }
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
}

Resources