Home > OS >  Input radio button's defaultChecked attribute prevents onClick function from being triggered
Input radio button's defaultChecked attribute prevents onClick function from being triggered

Time:05-25

<section key={i}>

    <input 
        type='radio'

        key={attribute.name   item.id}
        id={attribute.name   item.id}
        name={attribute.name}
        value={item.value}

        defaultChecked={i === 0}

        onClick={(event) => inputClick(attribute, event)}
    />
 
    <label 
        htmlFor={attribute.name   item.id}
    >
        {
            item.value
        }
    </label>
</section>

The code above is more or less what a .map() function is supposed to return in my React.js APP, creating input radio buttons for customizing a product before adding it to the cart state. All I did was remove some classes, etc. that were there for CSS purposes, etc.

Ideally, what is supposed to happen here is that...

  1. When rendering the product page for the first time, the very first input radio button that is returned by .map() should be checked by default. This works thanks to the "defaultChecked" attribute. No problems here.
  2. After I click a different input radio button (not the "defaultChecked" one), the checked input should change and all the other inputs should be left unchecked. As I understand it, input radio buttons with the same 'name' attribute do this automatically.
  3. When clicking the input radio button, the "onClick" function should trigger. This is where the code is not functioning as I wish it would.

The issue is that when my page renders for the first time and I click on an input radio button (other than the "defaultChecked") the "onClick" function does not trigger. It only triggers when I have clicked on a different input once and then on another.

A.k.a. it triggers on the second click. After that second click, it works as intended - every time a different input radio button is selected/clicked on - the function triggers, but not for the very first time.

I tested this with console.log("I am triggered") at the end of the "onClick" "inputClick(attribute, event)" function, and only on the second click would the console log "I am triggered".

I was able to fix the issue by removing the "defaultChecked" attribute. I think the issue might be tied to the fact that the "onClick" function is only able to be triggered when one input gains the "checked" attribute and another loses it, but the "defaultChecked" attribute does not count as an input being "fully checked" or something like that.

I could leave it at that, but the project that I am working on required me to have a default checked input radio button on the first-page render. So, I can't just delete the "defaultChecked" attribute and call it a day.

Any ideas on what could be causing this behavior?

UPDATE1

The following is the body of the inputclick() function:

    //* Handle input selection
    const inputClick = (attribute, event) => {

        //* Parse state
        let state = JSON.parse(JSON.stringify(itemState));

        //* Get all the required values from the clicked input
        const attributeId = attribute.id;
        const itemTargetValue = event.target.value;

        //* Check if the attribute is in state
        const attributeIs = state.some(item => item.id === attributeId);

        //* If the attribute does not exsist - add the attribute to state
        if(attributeIs === false) {

            const obj = {
                id: attributeId,
                selectedItem: itemTargetValue
            };

            state.push(obj);

            return setitemState(state);
        }

        //* If the attribute id already exsists in state
        if(attributeIs) {
            //* Find the index of the attribute in question
                const attributeIndex = state.map(object => object.id).indexOf(attributeId);
                const attributeInQuestion = state[attributeIndex].selectedItem;

            //* If the attribute's item's id is the same as the seelected input - do nothing
            if(attributeInQuestion === itemTargetValue) {
                return
            }
            //* If the attribute's item's id is not the same - change it to the new value
            if(attributeInQuestion !== itemTargetValue) {

                state[attributeIndex].selectedItem = itemTargetValue;

                console.log(state);

                return setitemState(state);
            }
        }
    };

CodePudding user response:

Here is the working code that fixes the issue.

Yes, there is some streamlining, for example, code shortening, etc. Yet, the difference that solves the issue is that...

The code that I had posted in the question originally was working. Meaning, that it was firing the inputClick() function and changing which input was selected, the problem was that...

...the defaultChecked logic in the was preventing the chosen input from being rendered as a selected input a.k.a. to change its CSS styling.

Bellow is the new onClick() function.

//* Handle input selection
    const inputClick = (product, attribute, event) => {
      let newCart = JSON.parse(JSON.stringify(cartState));

      const productId = product.id;
      const attributeId = attribute.id;
      const itemTargetValue = event.target.value;

      //* Find the product in cart state */
      const productIndex = newCart.map((object) => object.id).indexOf(productId);

      //* Find the attribute by id in question */
      const attributeIndex = newCart[productIndex].selectedAttributes.map(object => object.id).indexOf(attributeId);

      //* Change the products selected attribute item */
      newCart[productIndex].selectedAttributes[attributeIndex].selectedItem = itemTargetValue;

      setcartState(newCart);
    };

Below is what the "inside" of the looks like now.

    <input 
        type='radio'

        key={product.id   attribute.name   item.id}
        id={product.id   attribute.name   item.id}
        name={product.id   attribute.name}
        value={item.value}

        defaultChecked={product.selectedAttributes[selectedId].selectedItem === item.value}

        onChange={(event) => inputClick(product, attribute, event)}
      >
    </input>
  • Related