简体   繁体   中英

<select> does not change its selected <option> when setting a default value

I am creating a select component with a default value through props but suddenly when i tried to select an option, select do nothing.

I tried not to put a initial value it solve the problem but the program should not act like that.

//UserMaintenanceModal
class UserMaintenanceModal extends Component {
    state = {
        user_department: this.props.data.user_department,
        departments: [
            {id: 1, name: "IT"}, {id:2, name: "BM"}
        ]
    }

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

    render(){
        const { user_department } = this.state;
        return (
            <label>Department</label>
            <select 
                className="form-control form-control-sm" 
                name='user_department'
                value={user_department}
                onChange={this.handleChange}
             >
             {
              this.state.departments != null && this.state.departments.map(
                       department => 
                           <option 
                               key = {department.id} 
                               value = {department.name}
                            >
                                {department.name}
                            </option>
                      )
               }
               </select>
        )
    }
}

Solution

Sorry, my mistake. I did not show all of the source code. The reason it was not changing it because of this code which is inside a parent component.

//NavComponent

componentWillMount() {
    document.addEventListener('mousedown', this.handleClick, false);
}

componentWillUnmount() {
  document.removeEventListener('mousedown', this.handleClick, false);
}

I did get this code from here . It act to hide active dropdown nav menu when click outside of the component.

Take a look at this CodePen I've made: https://codepen.io/Gesma94/pen/QYYWKG

Since you are taking the value from the props, it means the parent Component keeps the value in the state (probably), so, when you select an option, you need to update the state of the parent Component, and in order to do that you need an handlerFunction passed to the Component with the options from the Parent.

class List extends React.Component {
    options = ["one", "two", "threee"];

    render() {
        const {handleChange, value} = this.props;
        return (
            <select value={value} onChange={handleChange}>
                {
                    this.options.map((option, index) =>
                        <option key={index} value={option}>
                            {option}
                        </option>
                 )}
            </select>
        );
    }
}

class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {value: "one"};
    }

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

  render() {
      return <List handleChange={this.handleChange} value={this.state.value} />
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

EDIT Ok, so.. One of the problem is what I said yesterday: you pass to the UserMaintenanceModal Component the default value, which is saved in the state of the App Component. But then, in UserMaintenanceModal Component you update the state of itself, and not the state of the App Component, so you kinda have an inconsistency.

Anyways, this is not your biggest problem: as far as I can see, there is some "confusion" (or maybe it's more probably that I don't fully understand what you want to achieve :) ). So, now I'm assuming that, as I said in the comment, you just want to display all the users belonging with the department selected!

I see that, inside the handleChange of App Component you save in the data property of the state the information about the currently clicked user (I don't know if this is mandatory or it was a try to achieve what I assumed). In case you did you want to save that info, that is redundant since you already have all these information in the users property: you could just save the userId or the position in the users array of the clicked user.

Then, I also don't understand why showModal is originally set to false and became true when you click on a user: this way it seems all the users should be visible at start, and once you clicked on one of them you kinda filter the users by the Department to which the clicked user belongs with. But if this is the case, I don't know why the select should became visible after.. :S

Finally, in the render() method of the App Component you should somehow say "hei, render only the users that belongs with the department selected", which you did not attempt (as far as I can see). In the following example I'm using a filter native function, but you could just have kept only the map function and return the user only if its user_department was equal to the currently selected.

Anyways, I also assumed that the selection should be visible from start, and I've forked your codepen, take a look at this and let me know if this is what you wanted: https://codepen.io/Gesma94/pen/aXXjvE

Notice that, in this example, the departments values are in the state of UserMaintenanceModal which isn't a good thing at all: you should retrieve the departments from the users array saved in the state of the App Component, and then pass them to the UserMaintenanceModal Component.. I mean, you should do something like "ok, let's see all my users and see all the departments that I have.. Ok now, that I have it, let's pass them to the UserMaintenanceModal .

You can put the default value prop in the component state and continue to use that.

Example

 class App extends React.Component { state = { options: ["foo", "bar", "baz"], selectedOption: this.props.defaultOption }; onChange = e => { this.setState({ selectedOption: e.target.value }); }; render() { const { options, selectedOption } = this.state; return ( <select value={selectedOption} onChange={this.onChange}> {options.map((option, index) => ( <option key={index} value={option}> {option} </option> ))} </select> ); } } ReactDOM.render(<App defaultOption="bar" />, document.getElementById("root"));
 <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> <div id="root"></div>

Problem

In my case, I wanted to switch or render different components to fill based on the selected field. Whenever I switched it, I could not be able to reset the selected fields of the rendered component. as a result, I could not show the right placeholder rather first option . This wrong and could confuse users.

Solution

I added the defaultValue in select tag. This the placeholder I want a user to see for the first time

I added the value in select tag. This helped me to track whenever users changed the mind or clean the data.

 <select name={inputName} id={inputId} className="input-controller-required" required onChange={onHandleInputChange} defaultValue={defaultValue} value={defaultValue} // I forgot to add value > <option disabled value="">{placeholder}</option> { options.map((item, index) => ( <option value={item.value} key={index}>{item.text}</option> )) } </select>

Thanks, @Jolly's answer and other contributors for support.

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