0

I am trying to run an onChange event on a select-react component, but I cannot change the default values. In addition to changing the options, I need to assign the selection values ​​to a state. When I remove the state, I am able to change the options normally.

I saved the code at codesandbox for verification.

const options = [
  {
    label: "Queue 1",
    value: 0
  },
  {
    label: "Queue 2",
    value: 1
  },
  {
    label: "Queue 3",
    value: 2
  }
];

const defaultOptions = [
  {
    label: "Queue 1",
    value: 0
  },
  {
    label: "Queue 3",
    value: 2
  }
];

const App = () => {
  const [selectedQueue, setSelectedQueue] = useState([]);

  const handleChange = async (e) => {
    const value = e.map((x) => x.value);
    console.log(value);

    // if you comment the two lines, below I have no problems
    setSelectedQueue(value);
    console.log(selectedQueue);
  };

  const CustomSelect = (props) => (
    <Select
      options={options}
      defaultValue={defaultOptions}
      className="custom-select"
      onChange={handleChange}
      {...props}
    />
  );

  return (
    <div className="App">
      Multiselect:
      <CustomSelect isMulti />
    </div>
  );
};
export default App;
Wagner Fillio
  • 395
  • 3
  • 19

1 Answers1

2

You are recreating CustomSelect component on each render, which means that the component is remounted on each render, and the defaultValue is applied again. Extract the component out of the App component (sandbox):

const CustomSelect = (props) => <Select className="custom-select" {...props} />;

And pass the props to the component, when you render it in App:

const App = () => {
  const [selectedQueue, setSelectedQueue] = useState([]);

  const handleChange = async (e) => {
    const value = e.map((x) => x.value);
    console.log(value);

    // if you comment the two lines, below I have no problems
    setSelectedQueue(value);
    console.log(selectedQueue);
  };

  return (
    <div className="App">
      Multiselect:
      <CustomSelect
        options={options}
        defaultValue={defaultOptions}
        onChange={handleChange}
        isMulti
      />
    </div>
  );
};
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • Thanks for the answer, but I only have one question! What if `options` and `defaultOptions` are also inside the` App` component? This data comes from the API, right when the component is loaded with `useEffect` – Wagner Fillio Mar 24 '21 at 21:33
  • Pass it as props to the `CustomSelect`. Look at the sandbox, and I'll expand the example here. – Ori Drori Mar 24 '21 at 21:34
  • I'm sorry, I couldn't help noticing that the state is late. while `console.log` shows 1, the state `selectedQueue` shows 0. and when `console.log` shows 2, `selectedQueue` shows 1. what can I do? I know that the state is asynchronous, but I lack the knowledge to get around it. – Wagner Fillio Mar 24 '21 at 22:25
  • The state would only update the next render. Move the `console.log()` to the body of the component. – Ori Drori Mar 24 '21 at 22:28
  • Here I have something related to this problem, help me? https://stackoverflow.com/questions/66607037/update-usestate-immediately – Wagner Fillio Mar 25 '21 at 01:10