Reputation: 115
I am trying to update the values in the form in child component to send to the api if I update an user but I am unable to change any values in the form and it only add or removes one character if I see the states. How can I update the values? using defaultValue solves it but it changes the input to be uncontrolled which i do not want.
...
#Parent Class
import React from "react";
import "./styles.css";
import Child from "./child";
export default class Parent extends React.Component {
constructor() {
super();
this.state = {
user: {
id: [1, 2, 3, 4, 5],
name: ["john", "wick", "ellen", "fork", "gow"]
}
};
}
render() {
return <Child user={this.state.user}> </Child>;
}
}
#Child Class
import React from "react";
import "./styles.css";
export default class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
user: {
id: "",
name: ""
}
};
}
handleSubmit = e => {
e.preventDefault();
};
handleChange = e => {
const data = { ...this.state.user };
data[e.currentTarget.name] = e.currentTarget.value;
this.setState({ user: data });
};
render() {
console.log(this.state);
console.log(this.props);
return (
<>
{this.props.user.id.map((id, index) => {
return (
<form onSubmit={this.handleSubmit}>
<label> id </label>
<input
type="text"
value={
this.props.user.id[index] !== "undefined"
? this.props.user.id[index]
: this.state.user.id
}
onChange={this.handleChange}
/>
<br />
<label> name </label>
<input
type="text"
value={
this.props.user.name[index] !== "undefined"
? this.props.user.name[index]
: this.state.user.name
}
onChange={this.handleChange}
/>
</form>
);
})}
}
</>
);
}
}
...
my sample code is
https://codesandbox.io/s/focused-shamir-y85v9?file=/src/parent.js:0
Upvotes: 1
Views: 463
Reputation: 120
EDIT: Heres a revised version of your code on codesandbox
https://codesandbox.io/s/quizzical-dew-jhx1b
Original:
So there are a few issues here. Firstly, instead of directly displaying the user values from props, I would store those in the state in the constructor.
For Example
class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
users: props.users
}
}
...
Then you can modify the state based on index. However, the way your data is organized is based on array indices which isn't the best. Instead, I would make each user an object
const myUser = {
id: 1,
name: 'John'
}
If the data you receive is already in that format, then you can parse it like so:
const ids = [1,2,3,4];
const names = ['John','Jenny','Jasper','Jaclyn'];
const users = ids.map((id, i) => ({ id, name: names[i] })); // uses arrow syntax
So the way your project is set up, you ARE modifying the state, however, you AREN'T displaying the state. (Because the id of the users in props never is undefined, lines 37,48 of your code)
So try parsing them into the state and then editing them based on the object index in the array, which will help keep the associated ids and names together without them getting mixed up.
Upvotes: 1
Reputation: 1
It's because, in handleChange
, e.currentTarget.name
is always null. So, you are setting state with empty values. Not entirely sure what you want to do, but if you do this,
handleChange = e => {
this.setState({ ...this.state, user: { id: e.target.value } });
};
you will see your id field update in your input boxes.
One thing you might consider is having your state handler be passed down from the parent, so each onChange will update the state. Then have your input props just be this.props.user.id[index]
.
If you provide what exactly you are trying to do, maybe I can be more help.
Upvotes: 0