0

I'm trying to save multiple values in one select and saving it in useState to use it again somewhere else. but it's not working I only get undefined values in my console.log .

here is the code:

import * as React from "react";
function App() {
  const [option, setOption] = React.useState({ width: 0, height: 0 });

  const options = [
    {
      label: "first",
      value: { width: 10, height: 10 },
    },
    {
      label: "second",
      value: { width: 20, height: 20 },
    },
    {
      label: "third",
      value: { width: 30, height: 30 },
    },
  ];
  const selectHandler = (e) => {
    setOption(e.target.value);
  };

  console.log(option.width);
  console.log(option.height);

  return (
    <div className="App">
      <h1>Test!</h1>
      <select value={options.value} onChange={selectHandler}>
        {options.map((option) => (
          <option key={option.label}>{option.label}</option>
        ))}
      </select>
      <p></p>
    </div>
  );
}

export default App;

I don't know if it's even possible... thanks in advance!

2
  • 1
    What are you hoping the state will hold after changing the select? It looks like you want state to be an array of objects? If you want to select multiple options in your select you should also use the multiple attribute on the select element. Commented Sep 19, 2022 at 10:54
  • @Andy sorry I couldn't explain my question correctly, no I don't want to select multiple options, I want my state to store width and height when selecting one option Commented Sep 19, 2022 at 11:05

2 Answers 2

2

You're setting your values in the state in a wrong manner. I've made some changes to your select handler function which hopefully solves your problem:

import * as React from 'react';
function App() {
  const [option, setOption] = React.useState({ width: 0, height: 0 });

  const options = [
    {
      label: 'first',
      value: { width: 10, height: 10 },
    },
    {
      label: 'second',
      value: { width: 20, height: 20 },
    },
    {
      label: 'third',
      value: { width: 30, height: 30 },
    },
  ];
  const selectHandler = (e) => {
    console.log(e.target.value);
    switch (e.target.value) {
      case 'first':
        setOption(options[0].value);
        break;
      case 'second':
        setOption(options[1].value);
        break;
      case 'third':
        setOption(options[2].value);
        break;
    }
  };

  console.log(option.width);
  console.log(option.height);

  return (
    <div className="App">
      <h1>Test!</h1>
      <select value={options.value} onChange={(e) => selectHandler(e)}>
        {options.map((option) => (
          <option key={option.label}>{option.label}</option>
        ))}
      </select>
      <p></p>
    </div>
  );
}

export default App;
Sign up to request clarification or add additional context in comments.

1 Comment

This is a big help, thank you so much!!
0
  1. Add a value attribute to each option. Assign it the option label.

  2. In selectHandler use find to locate the object in the options array with a label that matches the option value, and then add its value property to state.

  3. To log changes to state use useEffect to watch for those changes and then log the result (state updates are async so you wouldn't be able to log the change immediately).

const { useEffect, useState } = React;

function Example({ options }) {

  const [option, setOption] = React.useState({
    width: 0,
    height: 0
  });

  const selectHandler = (e) => {
    const { value } = e.target;
    const found = options.find(obj => obj.label === value);
    if (found) setOption(found.value);
  };

  useEffect(() => console.log(option), [option]);

  return (
    <div className="App">
      <h1>Test!</h1>
      <select onChange={selectHandler}>
        {options.map(option => (
          <option
            key={option.label}
            value={option.label}
            >{option.label}
          </option>
        ))}
      </select>
      <p></p>
    </div>
  );

}

const options=[{label:"first",value:{width:10,height:10}},{label:"second",value:{width:20,height:20}},{label:"third",value:{width:30,height:30}}];

ReactDOM.render(
  <Example options={options } />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.