OnChange event using React JS for drop down
Asked Answered
W

10

272
var MySelect = React.createClass({
     change: function(){
         return document.querySelector('#lang').value;
     },
     render: function(){
        return(
           <div>
               <select id="lang">
                  <option value="select" onChange={this.change}>Select</option>
                  <option value="Java" onChange={this.change}>Java</option>
                  <option value="C++" onChange={this.change}>C++</option>
               </select>
               <p></p>
               <p value={this.change}></p>
           </div>
        );
     }
});

React.render(<MySelect />, document.body);

The onChange event does not work.

Wholly answered 5/3, 2015 at 0:49 Comment(0)
D
446

The change event is triggered on the <select> element, not the <option> element. However, that's not the only problem. The way you defined the change function won't cause a rerender of the component. It seems like you might not have fully grasped the concept of React yet, so maybe "Thinking in React" helps.

You have to store the selected value as state and update the state when the value changes. Updating the state will trigger a rerender of the component.

var MySelect = React.createClass({
     getInitialState: function() {
         return {
             value: 'select'
         }
     },
     change: function(event){
         this.setState({value: event.target.value});
     },
     render: function(){
        return(
           <div>
               <select id="lang" onChange={this.change} value={this.state.value}>
                  <option value="select">Select</option>
                  <option value="Java">Java</option>
                  <option value="C++">C++</option>
               </select>
               <p></p>
               <p>{this.state.value}</p>
           </div>
        );
     }
});

React.render(<MySelect />, document.body);

Also note that <p> elements don't have a value attribute. React/JSX simply replicates the well-known HTML syntax, it doesn't introduce custom attributes (with the exception of key and ref). If you want the selected value to be the content of the <p> element then simply put inside of it, like you would do with any static content.

Learn more about event handling, state and form controls:

Deen answered 5/3, 2015 at 0:57 Comment(5)
how can i get the inner text without the value being the same as the inner text?Rustproof
@ZeroDarkThirty: The usual: event.target.textContentDeen
@FelixKling when I use textContent it print all the options inside de Select tag. What can I do to get only the selected ?Following
@Juan: Try event.target.slectedOptions[0].label.Deen
@FelixKin: use event.persist() in onChange function as target will be null if this is not used.Taber
T
92

React Hooks (16.8+):

const Dropdown = ({
  options
}) => {
  const [selectedOption, setSelectedOption] = useState(options[0].value);
  return (
      <select
        value={selectedOption}
        onChange={e => setSelectedOption(e.target.value)}>
        {options.map(o => (
          <option key={o.value} value={o.value}>{o.label}</option>
        ))}
      </select>
  );
};
Transit answered 18/7, 2019 at 9:28 Comment(0)
D
45
import React, { PureComponent, Fragment } from 'react';
import ReactDOM from 'react-dom';

class Select extends PureComponent {
  state = {
    options: [
      {
        name: 'Select…',
        value: null,
      },
      {
        name: 'A',
        value: 'a',
      },
      {
        name: 'B',
        value: 'b',
      },
      {
        name: 'C',
        value: 'c',
      },
    ],
    value: '?',
  };

  handleChange = (event) => {
    this.setState({ value: event.target.value });
  };

  render() {
    const { options, value } = this.state;

    return (
      <Fragment>
        <select onChange={this.handleChange} value={value}>
          {options.map(item => (
            <option key={item.value} value={item.value}>
              {item.name}
            </option>
          ))}
        </select>
        <h1>Favorite letter: {value}</h1>
      </Fragment>
    );
  }
}

ReactDOM.render(<Select />, window.document.body);
Dendrite answered 9/5, 2016 at 5:57 Comment(1)
very good. and you can see the result of change with this way <div> <p>{this.state.value}</p> </div>Dereism
M
11
  handleChange(value, selectOptionSetter) => {
     selectOptionSetter(value)
     // handle other stuff like persisting to store etc
   }

  const Dropdown = (props) => {
  const { options } = props;
  const [selectedOption, setSelectedOption] = useState(options[0].value);
  return (
      <select
        value={selectedOption}
        onChange={e => handleChange(e.target.value, setSelectedOption)}>
        {options.map(o => (
          <option key={o.value} value={o.value}>{o.label}</option>
        ))}
      </select>
  );
};
Muffin answered 22/4, 2021 at 19:43 Comment(0)
O
5

Now you can use it like this

import { useState } from 'react';
import './App.css';

function App() {
  const [selectedItem, setSelectedItem] = useState("Counter")
  const handleChange = (e) => {
    setSelectedItem(e.target.value)
  }
  return (
    <div className="App">
      <p>You have selected {selectedItem}</p>
      <select name='item-selected' value={selectedItem} onChange={handleChange}>
        <option value="Counter">Counter</option>
        <option value="useEffect">useEffect</option>
      </select>
    </div>
  );
}

export default App;
Outflow answered 25/2, 2023 at 12:1 Comment(1)
Most modern and recommended solution.Actinoid
D
4

If you are using select as inline to other component, then you can also use like given below.

<select onChange={(val) => this.handlePeriodChange(val.target.value)} className="btn btn-sm btn-outline-secondary dropdown-toggle">
    <option value="TODAY">Today</option>
    <option value="THIS_WEEK" >This Week</option>
    <option value="THIS_MONTH">This Month</option>
    <option value="THIS_YEAR">This Year</option>
    <option selected value="LAST_AVAILABLE_DAY">Last Availabe NAV Day</option>
</select>

And on the component where select is used, define the function to handle onChange like below:

handlePeriodChange(selVal) {
    this.props.handlePeriodChange(selVal);
}
Deify answered 15/4, 2020 at 5:31 Comment(0)
J
4

I'll add this here, in case it helps someone because this was the solution that helped me.

This is to get the SELECTED INDEX. Not for the value. (Worked for me because my options list was a list of numbers)

const [selectedOption, setSelectedOption] = useState(0)
<select onChange={event => setSelectedOption(event.target.options.selectedIndex)}>
Julijulia answered 9/11, 2021 at 7:0 Comment(0)
C
1

Thank you Felix Kling, but his answer need a little change:

var MySelect = React.createClass({
 getInitialState: function() {
     return {
         value: 'select'
     }
 },
 change: function(event){
     this.setState({value: event.target.value});
 },
 render: function(){
    return(
       <div>
           <select id="lang" onChange={this.change.bind(this)} value={this.state.value}>
              <option value="select">Select</option>
              <option value="Java">Java</option>
              <option value="C++">C++</option>
           </select>
           <p></p>
           <p>{this.state.value}</p>
       </div>
    );
 }
});
React.render(<MySelect />, document.body); 
Celibate answered 4/4, 2019 at 14:12 Comment(1)
Why are you adding this.change.bind in onChange?Douglas
P
0
var MySelect = React.createClass({
getInitialState: function() {
 

var MySelect = React.createClass({
 getInitialState: function() {
     return {
         value: 'select'
     }
 },
 change: function(event){
     event.persist(); //THE MAIN LINE THAT WILL SET THE VALUE
     this.setState({value: event.target.value});
 },
 render: function(){
    return(
       <div>
           <select id="lang" onChange={this.change.bind(this)} value={this.state.value}>
              <option value="select">Select</option>
              <option value="Java">Java</option>
              <option value="C++">C++</option>
           </select>
           <p></p>
           <p>{this.state.value}</p>
       </div>
    );
 }
});
React.render(<MySelect />, document.body); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Prospectus answered 26/6, 2020 at 18:32 Comment(0)
T
0

Hooks and TypeScript, with the state living in the parent component:

import React from 'react';

interface Option {
  value: string;
  label: string;
}

interface DropdownProps {
  options: Option[];
  selectedOption: string;
  onOptionChange: (value: string) => void;
}

const Dropdown: React.FC<DropdownProps> = ({ options, selectedOption, onOptionChange }) => {
  return (
    <select
      value={selectedOption}
      onChange={(e) => onOptionChange(e.target.value)}
    >
      {options.map((o) => (
        <option key={o.value} value={o.value}>
          {o.label}
        </option>
      ))}
    </select>
  );
};

const Parent: React.FC = () => {
  const options: Option[] = [
    { value: 'option1', label: 'Option 1' },
    { value: 'option2', label: 'Option 2' },
    { value: 'option3', label: 'Option 3' },
  ];

  const [selectedOption, setSelectedOption] = useState<string>(options[0].value);

  const handleOptionChange = (value: string) => {
    setSelectedOption(value);
  };

  return (
    <div>
      <Dropdown options={options} selectedOption={selectedOption} onOptionChange={handleOptionChange} />
      <p>Your selected option: {selectedOption}</p>
    </div>
  );
};

Transit answered 18/1 at 8:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.