0

I have a simple list where in each li there is radio inputs to choose from.

Whenever I select an option, all the inputs in all the other elements are updating with the same option. I included a unique id and a unique name as mentionned in React docs to regroup each group and make it separate but it didn't work.

I want to be able to select every element separately in the list. How to do so ?

https://codesandbox.io/s/affectionate-sun-i2khx?file=/src/App.js

import React, { useState } from "react";

export default () => {
  const initialList = [
    {
      id: "1",
      name: "John"
    },
    {
      id: "2",
      name: "Eric"
    },
    {
      id: "3",
      name: "Jonathan"
    }
  ];

  const handleChangeSelected = (event) => {
    setSelected(event.target.value);
    console.log(event);
  };

  const [list, setList] = useState(initialList);
  const [Selected, setSelected] = useState("option1");

  return (
    <div>
      <ul>
        <div>
          {list.map((item) => (
            <li key={item.id}>
              <div>
                <div className="users">{item.name}</div>
                <p />{" "}
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option1"
                  checked={Selected === "option1"}
                  onChange={handleChangeSelected}
                />
                <label for="huey">Option 1</label>
              </div>
              <div>
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option2"
                  checked={Selected === "option2"}
                  onChange={handleChangeSelected}
                />
                <label for="dewey">Option 2</label>
              </div>
              <div>
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option3"
                  checked={Selected === "option3"}
                  onChange={handleChangeSelected}
                />
                <label for="louie">Option 3</label>
              </div>
              <br />
            </li>
          ))}
        </div>
      </ul>
    </div>
  );
};

https://codesandbox.io/s/affectionate-sun-i2khx?file=/src/App.js

What I tried so far but didn't work to target the input to the corresponding id

  function handleSelected(e, id) {
    setSelected({
      ...Selected,
      [id]: Selected[id]
    });
  }
6
  • can you put selected in each object of list array ? Commented Apr 11, 2021 at 14:24
  • @DEEPAK What do you mean ? You can check my code here here Commented Apr 11, 2021 at 14:25
  • I checked that is why I am asking why not just put a selected key in each object of array! Commented Apr 11, 2021 at 14:27
  • like { id: "1", name: "John", selected: "option1" }, { id: "2", name: "Eric", selected: "option2" }, { id: "3", name: "Jonathan", selected: "option1" } Commented Apr 11, 2021 at 14:28
  • if you put this way handling would be easy enough Commented Apr 11, 2021 at 14:28

2 Answers 2

2

If you can put selected key in your intiallist array value then you can handle like below

import React, { useState } from "react";

export default () => {
  const initialList = [
    {
      id: "1",
      name: "John",
      selected: "option1"
    },
    {
      id: "2",
      name: "Eric",
      selected: "option2"
    },
    {
      id: "3",
      name: "Jonathan",
      selected: "option1"
    }
  ];

  const handleChangeSelected = (index, option) => {
    const cloneList = [...list];
    cloneList[index].selected = option;
    setList(cloneList);
  };

  const [list, setList] = useState(initialList);

  return (
    <div>
      <ul>
        <div>
          {list.map((item, index) => (
            <li key={item.id}>
              <div>
                <div className="users">{item.name}</div>
                <p />{" "}
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option1"
                  checked={item.selected === "option1"}
                  onChange={() => handleChangeSelected(index, "option1")}
                />
                <label for="huey">Option 1</label>
              </div>
              <div>
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option2"
                  checked={item.selected === "option2"}
                  onChange={() => handleChangeSelected(index, "option2")}
                />
                <label for="dewey">Option 2</label>
              </div>
              <div>
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option3"
                  checked={item.selected === "option3"}
                  onChange={() => handleChangeSelected(index, "option3")}
                />
                <label for="louie">Option 3</label>
              </div>
              <br />
            </li>
          ))}
        </div>
      </ul>
    </div>
  );
};

verify here https://codesandbox.io/s/thirsty-kirch-fwhpb?file=/src/App.js

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you very much! I see you completely changed handleChangeSelected while adding selected. Although this is working fine, is there any other method where it doesn't require adding selected at all ?
yes, that would increase few more lines. just like you have mentioned snippet in tried section
Thank you again. I see that checked is different in some fields, is it on purpose ?
yes, you have to put some conditions, on the first input my condition says if it has nothing by default set selected to first input
1

Selected state is just one string living above the map function. Consider declare it inside the map -

// refactor your main component
{list.map((item) => (
          <ListItem item={item} />  
))}





// create new ListItem component, Selected state declared here
const ListItem = ({item}) => {
  const handleChangeSelected = (event) => {
    setSelected(event.target.value);
    console.log(event);
  };

  const [Selected, setSelected] = useState("option1");
  return <li key={item.id}>
              <div>
                <div className="users">{item.name}</div>
                <p />{" "}
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option1"
                  checked={Selected === "option1"}
                  onChange={handleChangeSelected}
                />
                <label for="huey">Option 1</label>
              </div>
              <div>
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option2"
                  checked={Selected === "option2"}
                  onChange={handleChangeSelected}
                />
                <label for="dewey">Option 2</label>
              </div>
              <div>
                <input
                  type="radio"
                  id={item.id}
                  name={item.id}
                  value="option3"
                  checked={Selected === "option3"}
                  onChange={handleChangeSelected}
                />
                <label for="louie">Option 3</label>
              </div>
              <br />
            </li>
}

Now each mapped item manage its own Selected state

2 Comments

I like this method better because it doesn't require much change in the code. Can you please modify it [here] codesandbox.io/s/thirsty-kirch-fwhpb?file=/src/App.js ? For some reason I have error and I think I'm missing something.
Edit my answer with 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.