novafluff
novafluff

Reputation: 911

React select onChange doesn't use the options value

I have this select component

<select
    value={(this.state.selectedVersion)}
    disabled={(this.state.versionDisable)}
    onChange={this.handleVersionChange}
>
    <option disabled hidden>Välj version</option>
    {
        this.state.versions.map((object, i) => {
            return (
                <option key={i} value={object}>
                    {object.text}{object.lastModified}
                </option>
            )
        })
    }
</select>

here I want the onChange event to take the options value which I have logged is the thing I want and use it as value but when I send it to my onChange handler

handleVersionChange(event){
    console.log(event);
    this.setState({selectedVersion: event.target.value});
    console.log(this.state.selectedVersion);
}

The first console.log that logs the event that got sent I get some proxy object that I don't know what it is or were it is from. I don't know if I get this problem since I created the options with the map. Anyone know what I am doing wrong?

Upvotes: 1

Views: 4466

Answers (4)

William Chou
William Chou

Reputation: 772

Trying console logging in componentWillReceiveProps instead of inside your handle change function.

SetState is asynchronous.

Upvotes: 0

Chirag Ravindra
Chirag Ravindra

Reputation: 4830

I still think the problem is setting the value attribute on the option element as an Object. Consider using a string instead. You can always reverse lookup a value in your change handler from the original array to get the full object.

In the following example I use an attribute I created called id to use as the select option value. This value can be any unique identifier in your object which is a simple type like string or number. The same value can be used to reverse lookup the full object

Sample JS Fiddle

class SelectApp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    	items: [
      	{ text: "Learn JavaScript", id: 1 },
        { text: "Learn React", id: 2 },
        { text: "Play around in JSFiddle", id: 3 },
        { text: "Build something awesome", id: 4 }
      ]
    }
    selected:null
  }
  
  handleChange = (e)=>{
    // Get the selected value which is a string
  	var selectedId = e.target.value;
    console.log(selectedId);
    // Reverse look up on the array to find the full object
    var selected = this.state.items.find((d)=>(d.id==selectedId));
    console.log(selected);
    // Update state with object
    this.setState({selected});
  }
  
  render() {
    return (
      <div>
        <select onChange={this.handleChange}>
        <option disabled selected>Select</option>
        {this.state.items.map((item, i) => (
        	<option key={i} value={item.id}>{item.text}</option>
        ))}
        </select>
      </div>
    )
  }
}

ReactDOM.render(<SelectApp />, document.querySelector("#app"))

Upvotes: 1

Elkhan  Mamedov
Elkhan Mamedov

Reputation: 91

Why do you put another pair of braces inside curly ones: {(this.state.selectedVersion)}? Am I missing something: {this.state.selectedVersion}?

Upvotes: 0

LaPoule
LaPoule

Reputation: 323

Your handleVersionChange need to be a listen function. Replace by this :

 handleVersionChange = (event) => {
     console.log(event);
     this.setState({selectedVersion: event.target.value});
     console.log(this.state.selectedVersion);
 }

Or in your constructor add :

this.handleVersionChange = this.handleVersionChange.bind(this)

Upvotes: 0

Related Questions