Radio Button Background Not Changing on First Click in React Component

I’m working on a React form where I’m trying to change the background color of a label when a radio button is selected, but when I click/check the button it first update the state and on second click it shows me the background color.

I’m using a combination of onChange and checked attributes to manage the radio button state.

I have go through the Chat-GPT but it is still not answering me correctly

Below is the code for the Task component and CSS.

import React, { useState } from 'react';

export default function Task() {
  let [formData, setformData] = useState({
    uName: '', 
    uGender: '', 
    uMedals: 0, 
  });

  let handleForm = (e) => {
    let { name, value } = e.target;

    e.preventDefault();

    if (name === 'uMedals') {
      value = parseInt(value);

      if (value <= 0)
          value = 0;

      if (value > 20) 
          value = formData.uMedals;
    }

    setformData((formData) => ({
      ...formData,
      [name]: value,
    }));
  };

  return (
    <div className='parent-container'>
      <div className='content-wrapper'>
        <div className='left'>
          <form className='form-wrapper'>
            <div className='name-wrapper'>
              <label>Name</label>
              {/* Name input */}
            </div>
            <div className='toogle-wrapper'>
              <label className='lbl-gen'>Gender</label>
              <div className='wrapper'>
                <div className='custom-input'>
                  <input
                    type='radio'
                    id='female'
                    name='uGender'
                    value='female'
                    onChange={handleForm}
                    checked={formData.uGender === 'female'}
                  />
                  <label htmlFor='female'>Female</label>
                </div>
                <div className='custom-input'>
                  <input
                    type='radio'
                    id='male'
                    name='uGender'
                    value='male'
                    onChange={handleForm}
                    checked={formData.uGender === 'male'}
                  />
                  <label htmlFor='male'>Male</label>
                </div>
              </div>
            </div>
            <button style={{ width: '320px' }}>Add</button>
          </form>
        </div>
      </div>
    </div>
  );
}

The below is the CSS code of above Task component

.custom-input input[type=radio] {
    display: none;
}
.custom-input label {
    display: block;
    padding: 6px 8px;
    color: #fff;
    font-weight: bold;
    text-align: center;
    transition: all 0.4s ease;
    cursor: pointer;
    border-radius: 4px;
    background-color: #717762;
}
.custom-input input[type='radio']:checked + label {
    background-color: #f5f5f5; 
    color: #000;
}

You need to remove e.preventDefault() from handleForm function to change background color on first click.

function Task() {
  const [formData, setformData] = React.useState({
    uName: "",
    uGender: "",
    uMedals: 0,
  });

  const handleForm = (e) => {
    let { name, value } = e.target;
    if (name === "uMedals") {
      value = parseInt(value);
      if (value <= 0) value = 0;
      if (value > 20) value = formData.uMedals;
    }
    setformData((formData) => ({
      ...formData,
      [name]: value,
    }));
  };

  return (
    <div className="parent-container">
      <div className="content-wrapper">
        <div className="left">
          <form className="form-wrapper">
            <div className="name-wrapper">
              <label>Name</label>
              {/* Name input */}
            </div>
            <div className="toogle-wrapper">
              <label className="lbl-gen">Gender</label>
              <div className="wrapper">
                <div className="custom-input">
                  <input
                    type="radio"
                    id="female"
                    name="uGender"
                    value="female"
                    onChange={handleForm}
                    checked={formData.uGender === "female"}
                  />
                  <label htmlFor="female">Female</label>
                </div>
                <div className="custom-input">
                  <input
                    type="radio"
                    id="male"
                    name="uGender"
                    value="male"
                    onChange={handleForm}
                    checked={formData.uGender === "male"}
                  />
                  <label htmlFor="male">Male</label>
                </div>
              </div>
            </div>
            <button style={{ width: "320px" }}>Add</button>
          </form>
        </div>
      </div>
    </div>
  );
}

ReactDOM.render(<Task />, document.getElementById("root"));
.custom-input input[type=radio] {
    display: none;
}
.custom-input label {
    display: block;
    padding: 6px 8px;
    color: #fff;
    font-weight: bold;
    text-align: center;
    transition: all 0.4s ease;
    cursor: pointer;
    border-radius: 4px;
    background-color: #717762;
}
.custom-input input[type='radio']:checked + label {
    background-color: #f5f5f5; 
    color: #000;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

3

In your CSS, you’re using the sibling combinator (+), which only applies styles to the that is immediately following the . This means that your CSS rule will only affect labels that are direct siblings of the radio inputs.

Keep the label immediately after the input within the same .custom-input container.

2

You are experiencing a conflict between React event system logic and the browser.

TLDR: Removing e.preventDefault() solves your issue without any actual downsides.

In an attempt to normalize the change handling for radio buttons and checkboxes across multiple browsers, React hijacks the browser’s click event. Having a preventDefault on the event causes the browser not to visually update the input but it doesn’t stop setting the state.

Setting a state triggers a re-render of the component. If you would add Checked: {formData.uGender} somewhere, like below your button, you would see that it does re-render as the value is updated. The input isn’t updated however, since preventDefault interfered.

Even though the first click didn’t show the visual effect, it did set the state. When clicking for the second time, it sets the state yet again and re-renders. Updating the visual effect is probably prevented this time as well, but as we already had the matching state from the previous click, the controlled input checked={formData.uGender === 'female'} is now true and thus is shown visually as well.

According to MDN, the checked attribute for checkboxes and radio buttons doesn’t actually reflect the selected value, but the initial default value. So there is a disconnect between the checked attribute, and whether or not the state of the input is checked or not. The conflict between the browser event logic and React’s event logic could be affected by this.

While debugging, I noticed that if you put a console.log in handleForm it only prints for the first click.

This has been around since at least 2015. Given the comment in the source code, the need to normalize the change event to a click event was due to IE8. Since this is no longer a very common browser, one could assume that is would be safe to remove. The React team seems to be more prone to eventually removing the React event logic altogether in favor for a more mature browser event logic.

Either way, there is no need for the e.preventDefault() in your case, since you do want the default behavior: to check the radio button.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật