0

On my select element in React, the first couple of selects aren't changing the value, but then they start changing the value to the previous selected option, like if I select the option FRITOS, the value is undefined, then when I select the option COFFEE, the value is FRITOS, and then when I select FRITOS again, the value goes to COFFEE. Really confused what's going on haha.

My function that's setting the state

  changeGroup = (event) => {
    this.setState({ [event.target.name]: event.target.value });
    console.log(this.state.groupSelected);
    const bugQuery = {
      GroupID: this.state.groupSelected,
    };
    console.log(bugQuery);
    console.log(this.props.bugs);
    if (this.state.groupSelected !== undefined) {
      this.props.getBugs(bugQuery);
    }
  };

My select element

     <select
                style={{ border: "1px solid white", fontSize: "2.7vh" }}
                name="groupSelected"
                value={this.state.groupSelected}
                onChange={this.changeGroup}
              >
                <option value="FRITOS">FRITOS</option>
                <option value="5AFSA">5AFSA</option>
                <option selected>Groups</option>
    </select>

CalebN99
  • 99
  • 2
  • 10
  • 1
    Does this answer your question? [Why calling react setState method doesn't mutate the state immediately?](https://stackoverflow.com/questions/30782948/why-calling-react-setstate-method-doesnt-mutate-the-state-immediately) –  May 30 '20 at 00:45
  • The setState methods work asyncronously, so you can't rely that the first line of the changeGroup function mutates the state. Use the event.target.value instead of this.state.groupSelected inside the function and you may achieve what you are trying to – Rander Gabriel May 30 '20 at 00:48
  • The fix is to compose a new state object based on the current state and the `event`, and use that both in your setState call and the props method call. –  May 30 '20 at 00:49
  • @RanderGabriel I am using event.target.value? – CalebN99 May 30 '20 at 01:27
  • In my comment i meant that the value on the this.state doesnt mutate right after you call setState, so if you access this.state it is in fact storing the previous value – Rander Gabriel May 30 '20 at 04:42

1 Answers1

0

[Previous answer was dumb, let's edit !]

You can trigger a re-render by putting your select in a component :

import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import "./style.css";

class App extends Component {
  constructor() {
    super();

    this.options = ["FRITOS", "SAFSA"];

    this.state = {
      name: "React",
      groupSelected:''
    };
  }

  changeGroup = event => {
    this.setState({[event.target.name]: event.target.value }, () => console.log(this.state.groupSelected));

  };

  render() {
    return (
      <div>
        <Hello name={this.state.name} />

        <MySelect 
          options={this.options} 
          selectedOption={this.state.groupSelected} 
          onSelectChange={this.changeGroup} />

        <div>groupSelected = {this.state.groupSelected}</div>
      </div>
    );
  }
}

class MySelect extends Component {
  constructor(props) {
    super(props);

    this.options = ["FRITOS", "SAFSA"];
  }

  buildSelectOptions = () => {
    return this.props.options.map(option => (
      <option key={option} value={option}>
        {option}
      </option>
    ));
  };

  render() {
    return (
      <>
        <select
          style={{ border: "1px solid white", fontSize: "2.7vh" }}
          name="groupSelected"
          value={this.props.groupSelected}
          onChange={this.props.onSelectChange}
        >
          {this.buildSelectOptions()}
          <option selected>Groups</option>
        </select>
      </>
    );
  }
}

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

Here is the repro on Stackblitz

I kept it the old way since you are using this.setState, but if you can, move to an up to date version of react and use functional components and hooks, this won't be a problem anymore.

Quentin Grisel
  • 4,794
  • 1
  • 10
  • 15