Shubham Singhvi
Shubham Singhvi

Reputation: 422

Set state false to checked radio buttons in map Component

function EachData({ data, index, open }) {
  const [isOpen, setisOpen] = useState(open);

  const toggle = (e) => {
    setisOpen((prev) => !prev);      
  };

  return (
    <tr>
      {/*<td></td>'s ... */}
      <td>
        <div className="functions">
          {!isOpen ? (
            <>
              <label className="far fa-edit" htmlFor={`label-${index + 1}`}>
                <input type="radio" name="edit" id={`label-${index + 1}`} onChange={toggle} />
              </label>
              <label className="far fa-trash"></label>
            </>
          ) : (
            <>
              <label className="far fa-circle-check"></label>
              <label className="far fa-times-circle" htmlFor={`label-${index + 1}`} >
                <input type="radio" name="edit" id={`label-${index + 1}`} onChange={toggle} />
              </label>
            </>
          )}
        </div>
      </td>
    </tr>
  );
}

export default EachData;

App.js

array.map((data, index)=>{
  return(
    <EachData data={data} index={index} isOpen={false}/>
  )
})

When I check the radio buttons the jsx changes as expected, but after checking another radio button the previous one's state remains true. How do I set those elements state to false ?

Upvotes: 1

Views: 791

Answers (3)

Ahmad
Ahmad

Reputation: 1479

You should use useRef instead of id, here I make some logic with useRef I hope this would be helpful.

As per my understand, when you click on radio button in map function this will be activated and when you click another radio button previous radio button is still showing active, In this code I create two useRef as you see the below code, one is taking for all indexes and second for removing previous radio button active. I hope you understand this code, if you know DOM.

function EachData({ data, index, open }) {
  const [isOpen, setisOpen] = useState(open);

  const radioRef = useRef([]);
  const previousRadioRef = useRef([]);

  const toggle = (i) => {
    setisOpen((prev) => !prev);
    if (previousRadioRef.current && previousRadioRef.current[0] !== radioRef.current[i]) {
      if (radioRef.current[i]) {
        if (previousRadioRef.current.length) {
        previousRadioRef.current[0].checked = false;
        previousRadioRef.current = [];
      }
      radioRef.current[i].checked = true;
      previousRadioRef.current.push(radioRef.current[i]);
    }
    } else if(previousRadioRef.current && previousRadioRef.current[0]) {
       previousRadioRef.current[0].checked = false;
       previousRadioRef.current = [];
   }
  };

  return (
    <>
      <tr>
      <td>
        <div className="functions">
          {!isOpen ? (
            <>
              <label className="far fa-edit">
                <input type="radio" name="edit" ref={ref => (radioRef.current[index] = ref)} onChange={() => toggle(index)} />
              </label>
              <label className="far fa-trash"></label>
            </>
          ) : (
            <>
              <label className="far fa-circle-check"></label>
              <label className="far fa-times-circle">
                <input type="radio" name="edit" ref={ref => (radioRef.current[index] = ref)} onChange={() => toggle(index)} />
              </label>
            </>
          )}
        </div>
      </td>
    </tr>
    </>
  );
}

export default EachData;


array.map((data, index)=>{
  return(
    <EachData data={data} index={index} open={false}/>
  )
})

Upvotes: 1

First Arachne
First Arachne

Reputation: 829

You can set state with the name of radio input. Reference: http://react.tips/radio-buttons-in-reactjs/

Upvotes: 0

iamhuynq
iamhuynq

Reputation: 5529

You should store isOpen state in your array data, not in EachData component

const [array, setArray] = useState();

const toggle = idx => {
    const newArray = array.map((item, index) => {
        if (idx == index) return {
           ...item,
           isOpen: !item.isOpen
        }
        return item
    })
    setArray(newArray);
}

array.map((data, index) => {
    return <EachData data={data} index={index} isOpen={data.isOpen} toggle={toggle} />;
});

function EachData({ data, index, isOpen, toggle }) {
    return (
        <tr>
            {/*<td></td>'s ... */}
            <td>
                <div className="functions">
                    {!isOpen ? (
                        <>
                            <label className="far fa-edit" htmlFor={`label-${index + 1}`}>
                                <input
                                    type="radio"
                                    name="edit"
                                    id={`label-${index + 1}`}
                                    onChange={() => toggle(index)}
                                />
                            </label>
                            <label className="far fa-trash"></label>
                        </>
                    ) : (
                        <>
                            <label className="far fa-circle-check"></label>
                            <label className="far fa-times-circle" htmlFor={`label-${index + 1}`}>
                                <input
                                    type="radio"
                                    name="edit"
                                    id={`label-${index + 1}`}
                                    onChange={() => toggle(index)}
                                />
                            </label>
                        </>
                    )}
                </div>
            </td>
        </tr>
    );
}

Upvotes: 1

Related Questions