death stranding
death stranding

Reputation: 115

Unable to update the state value in React Js forms

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

Answers (2)

Brad Harker
Brad Harker

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

user11609757
user11609757

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

Related Questions