AndreVitorio
AndreVitorio

Reputation: 930

How to make a select input that is dependent on other inputs to always show a default value in React?

I have two radio buttons: radio1 and radio2, and one select input. The Select values depend on the radio buttons. I want to set the select value to 1 whenever I select radio1. I've tried setting defaultValue and value to the select input but every time I switch back to radio1 from radio2, the value is always set to 2.

Here's my code, any help is truly appreciated:

import "./styles.css";
import { useState } from "react";

const selectItems = {
  name: "size",
  fields: {
    radio1: [
      {
        value: "1"
      },
      {
        value: "2"
      }
    ],
    radio2: [
      {
        value: "2"
      },
      {
        value: "3"
      },
      {
        value: "4"
      }
    ]
  }
};

const App = () => {
  const [values, setValues] = useState({ radio: "radio1", select: "2" });
  const handleChange = (name, value) => {
    setValues((s) => {
      return { ...s, [name]: value };
    });
  };

  return (
    <div className="App">
      <h2>
        How do I make the Select always be '1' when Radio1 is selected after
        selecting Radio2?
      </h2>
      <input
        type="radio"
        id="radio1"
        value="radio1"
        name="radio"
        onChange={() => handleChange("radio", "radio1")}
      />
      <label htmlFor="radio1">Radio1</label>
      <input
        type="radio"
        id="radio2"
        value="radio2"
        name="radio"
        onChange={() => handleChange("radio", "radio2")}
      />
      <label htmlFor="radio2">Radio2</label>
      <br />
      <select
        id="size"
        name="size"
        onChange={(e) => handleChange("select", e.target.value)}
      >
        {selectItems.fields[values.radio].map(({ value }) => {
          return (
            <option key={value} value={value}>
              {value}
            </option>
          );
        })}
      </select>
    </div>
  );
};

export default App;


example: https://codesandbox.io/s/goofy-danny-p1l3s?file=/src/App.js:0-1460

Edit:

As suggested by some answers, I have tried setting 'selected' as true. In fact, I have tried this before and forgot to mention it on my question. This seem to work, it gives me the desired effect on the browser, but then I get this error on the console:

Warning: Use the `defaultValue` or `value` props on <select> instead of setting `selected` on <option>.

Upvotes: 2

Views: 940

Answers (3)

luffy
luffy

Reputation: 226

The main problem here is <option> is taking the same key value. When you are selecting radio2, key becomes 2.Then you are selecting radio1 and for that <select> has <option> with key=2. That is why <select> value not changing. The proof is if you change all <option> values unique, example for radio1 {1, 2} and for radio2 {3, 4, 5} your code works fine.

There may be multiple workarounds but the proper way to solve this is having unique id for each of the <option>.

const selectItems = {
  name: "size",
  fields: {
    radio1: [
      {
        value: "1",
        id: 1
      },
      {
        value: "2",
        id: 2
      }
    ],
    radio2: [
      {
        value: "2",
        id: 3
      },
      {
        value: "3",
        id: 4
      },
      {
        value: "4",
        id: 5
      }
    ]
  }
};
------------------------------------------
<select
        id="size"
        name="size"
        onChange={(e) => handleChange("select", e.target.value)}
      >
        {selectItems.fields[values.radio].map(({ value, id }) => {
          return (
            <option key={id} value={value}>
              {value}
            </option>
          );
        })}
      </select>

Upvotes: 1

Majid M.
Majid M.

Reputation: 4954

You can define a new state which is called defaultValue. As a result, with setting the value property of select tag by defaultValue, you can achieve your goal:

const App = () => {
  const [values, setValues] = useState({ radio: "radio1", select: "2" });
  const [defaultValue, setDefaultValue] = useState(0);
  const handleChange = (name, value) => {
    setValues((s) => {
      return { ...s, [name]: value };
    });
  };

  useEffect(() => {
    setDefaultValue(selectItems.fields[values.radio][0].value);
  }, [values]);
  return (
    <div className="App">
      <h2>
        How do I make the Select always be '1' when Radio1 is selected after
        selecting Radio2?
      </h2>
      <input
        type="radio"
        id="radio1"
        value="radio1"
        name="radio"
        onChange={() => handleChange("radio", "radio1")}
      />
      <label for="radio1">Radio1</label>
      <input
        type="radio"
        id="radio2"
        value="radio2"
        name="radio"
        onChange={() => handleChange("radio", "radio2")}
      />
      <label for="radio2">Radio2</label>
      <br />
      <select
        id="size"
        name="size"
        value={defaultValue}
        onChange={(e) => handleChange("select", e.target.value)}
      >
        {selectItems.fields[values.radio].map(({ value }, index) => {
          return (
            <option key={value} value={value}>
              {value}
            </option>
          );
        })}
      </select>
    </div>
  );
};

export default App;

Edit laughing-engelbart-ok8jy

Upvotes: 0

Oleg Gulevskyy
Oleg Gulevskyy

Reputation: 92

Element <option> has property selected that is responsible for determining which item is currently selected. That is the property that will help you to decide which item should be currently selected at any given time. To illustrate this, I have added the following check to your element: <element selected={value === '1'}> and now every time you change the radio from radio1 to radio2 the value changes to 1 as you asked in your question.

My response here is more of a guidance, do not treat as exact step by step instruction as I did not think of any other ways that your program might work or handle different behaviours.

Upvotes: 0

Related Questions