Home > Software engineering >  React select option with multiple object values
React select option with multiple object values

Time:09-19

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!

CodePudding user response:

you are setting your values in the state in a wrong manner...here..i have made some changes to your select handler function. hope it 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;

CodePudding user response:

  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>

  • Related