简体   繁体   中英

How to pass an object value in a form's select field onChange (using React, without Redux)

I'm currently working on a react component with a simple form (no redux, just using react-bootstrap for styling)

I'm pulling data from a database in the following form:

[
  {
    "id":"123",
    "name":"Amy Pond",
    "age":"22",
    "reputation":22000
  },
  {
    "id":"124",
    "name":"Clara Oswald",
    "age":"24",
    "reputation":35000
 }
 ...
]

and putting it into an object:

let userlist = [];
userlist = addUsers(this.state.users);

I used map to populate a dropdown based on this data, and can correctly set the state of the user to the selected one from the drop down:

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange}
>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.name}>
       {r.name}
     </option>
  )}
</FormControl>

using handleChange()

handleChange(event) {
  this.setState({
    value: event.target.value,
    // reputation: ???? // here's where I'm running into issues
    // age: ???????  // and here
});

My problem is, I need the user's age and reputation in the handleChange function to set their states accordingly. I've tried passing just r instead of r.name but I get [object Object] back.

console.log ("Handle Change Value: " + event.target.value);

if I try event.target.value.name I get undefined back.

The only thing that has sort of worked so far, is using JSON.stringify, but I feel like that's not the right way to do this. I've also thought about just searching through the objects once I've gotten just the name, but if there was a lot of objects I think that would be extremely inefficient? I'm also not sure how to do that.

Can anyone please help me find a way to pass these two extra values so I can set the state? Is map even the best way to create the options? I honestly feel like this is such a simple thing, but I'm still new to react and I've been struggling with this for far too long!

Any ideas / changes / comments / way to make this better would be much appreciated! I realize that perhaps using something like redux-form would make this easier, but I'm hoping there's a simple way to do it without that just for now.

Edit: onChange should have been set to onChange = {this.handleChange} , just pasted the wrong code from my attempts to troubleshoot. I'm binding this in the constructor:

constructor(props) {
  super(props);
  ...
  this.handleChange = this.handleChange.bind(this);
}

Use the user ID as the value in each option , then in handleChange find the user in your userlist to access all the user's properties:

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange.bind(this)}
>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.id}>
       {r.name}
     </option>
  )}
</FormControl>

handleChange(event) {
  const userId = event.target.value;
  const user = userlist.find(u => u.id === userId);
  this.setState({
    value: user
  });
}

Also, the way you are passing the onChange property might cause issues. It's hard to tell without seeing all your code, but make sure that you pass in a reference to your handleChange function (see above in my answer) rather than calling it right there (as in your question: onChange={this.handleChange()} , unless your this.handleChange function returns a function).

It could be a problem with the way you've set your event listener, settings onChange={this.handleChange()} would cause the listener to fire right away. Using onChange={this.handleChange} correctly sets the listener.

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange}>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.name}>
       {r.name}
     </option>
  )}
</FormControl>

See here for more on events.

You can then use find() in your event handler to locate the user:

handleChange(event) {
  let user = users.find(u => u.name === event.user.name);
  this.setState({user: user});
}

you can use option tag attribute and json to encode/decode like this:

<FormControl
        id="user"
        componentClass="select"
        onChange={this.handleChange.bind(this)}
    >
        {userlist.map((r, i) =>
            <option
                key={i}
                value={r.id}>
                {r.name}
                data={JSON.stringify(r)}
            </option>
        )}
    </FormControl>;

    handleChange(event)
    {
        if (e.target.options && e.target.selectedIndex) {
            const user = e.target.options[e.target.selectedIndex].getAttribute('data');
            this.setState({
                value: user
            });
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM