0

I would like to know how can I make any button changing color when selected.

Knowing that you can only selected one button at the time for each value.

Like if you click on 'White', the Black button can't have the same background color. Same for the Size, if 'L' is selected, and you click on 'S' then, 'L' take the default color and 'S' the background color when an element is selected.

What it look like now

Thanks in advance to anyone who tries to help me!

I've tried to use If Statement but I'm not sure I'm doing it right.

           {values.map((value) => {
              
              const id = `option-${name}-${value}`;
              const checked = setSelectedOption[name] === value;

              const [bgSelected, setBgSelected] = useState(false);

              const handleClick = () => {
                  setBgSelected(!bgSelected);
              }

              const handleSelected = () => {
                setSelectedOption(name, value);
                if (bgSelected === true) {
                  setBgSelected(false);
                  handleClick()
                } else {
                  setBgSelected(true);
                  handleClick()
                 }
                
              }



              return (
                <div key={id} className="product-option-value text-left">
                  <div 
                    type="button" 
                    checked={checked}
                    name={name}
                    value={value}
                    id={id}
                   // onChange={() =>setSelectedOption(name, value)}
                    className=""
                  />
                  <label 
                    htmlFor={id}
                    //onClick={handleClick}
                    className={bgSelected ? "bg-blue-800" : "bg-blue-200"}
                    onClick={handleSelected}

                  >{value}</label>


                </div>
              )
            })}

          </div>
imnotremi
  • 19
  • 7

1 Answers1

0

It seems like you are calling the wrong property from useProductOptions to determine if your product has been selected, you are using setSelectedOption[name] instead of the selectedOptions[name].

Based on this one value (selectedOptions[name]) you can also determine if a value has been selected so you do not need to create an extra state for the background.

Try and use:

function ProductForm({ product }) {
  const { options, selectedVariant, selectedOptions, setSelectedOption } =
    useProductOptions();

  const isOutOfStock = !selectedVariant?.availableForSale || false;

  return (
    <div className="drop-shadow-xl bg-white rounded-xl p-10 w-7/12">
      <h1 className="font-bold text-3xl">{product.title}</h1>
      <ProductPrice
        className="font-light text-lg pb-3"
        data={product}
        variantId={selectedVariant.id}
      />

      <div className="product-option">
        {options.map(({ name, values }) => {
          if (values.length === 1) {
            return null;
          }
          return (
            <div
              key={name}
              className="product-option-group sm:grid-cols-2 flex items-center gap-3"
            >
              <legend className="product-option-name font-bold text-lg py-3 w-12">
                {name}
              </legend>

              {values.map((value) => {
                const id = `option-${name}-${value}`;
                const checked = selectedOptions[name] === value;

                return (
                  <div key={id} className="product-option-value text-left">
                    <div
                      type="button"
                      checked={checked}
                      name={name}
                      value={value}
                      id={id}
                      className=""
                    />
                    <label
                      htmlFor={id}
                      className={checked ? "bg-blue-800" : "bg-blue-200"}
                      onClick={() => setSelectedOption(name, value)}
                    >
                      {value}
                    </label>
                  </div>
                );
              })}
            </div>
          );
        })}
      </div>

      <AddToCartButton
        disabled={isOutOfStock}
        className="add-to-cart font-bold text-md p-2 rounded-3xl mt-3 bg-slate-300 hover:bg-slate-400"
      >
        {isOutOfStock ? "Out of stock" : "Add to cart"}
      </AddToCartButton>
    </div>
  );
}

=== old answer before the post update ===

I am not sure why your code is not throwing errors, but you should (and can) not use a useState inside of a map.

You could write this component using just one state, as below.

A working example can be found at this codesandbox

const values = [
  {
    id: 1,
    name: "test",
    value: "option 1"
  },
  {
    id: 2,
    name: "test",
    value: "option 2"
  },
  {
    id: 3,
    name: "test",
    value: "option 3"
  }
];
const MyComponent = () => {
  const [selectedValue, setSelectedValue] = useState(values[0]);

  return (
    <>
      {values.map(({ id, value, name }) => {
        const isSelected = selectedValue === id;
        return (
          <div key={id} className="product-option-value text-left">
            <input
              type="radio"
              checked={isSelected}
              name={name}
              value={value}
              id={id}
              onChange={() => setSelectedValue(id)}
            />
            <label
              htmlFor={id}
              style={{ background: isSelected ? "red" : "blue" }}
            >
              {value}
            </label>
          </div>
        );
      })}
    </>
  );
};

Xiduzo
  • 897
  • 8
  • 24
  • Thank you for your response but it doesn't work. Maybe I need to specified that is in a function, the post is edit you can now see the whole code. Btw the values an id came from a Shopify API. If i modify the value like in your response "const [selectedValue, setSelectedValue] = useState(values[0]);" that's doesn't give the name of the value. – imnotremi Dec 01 '22 at 15:42
  • I can't change the code on my post :/ – imnotremi Dec 01 '22 at 15:44
  • the example above should be used as an example of how you could set it up, it is not meant to be used for copy-paste into your specific code :) If you could provide a https://stackoverflow.com/help/minimal-reproducible-example, for example with a code-sandbox link I could have a look againt – Xiduzo Dec 01 '22 at 15:49
  • You can find it on github : https://github.com/imnotremi/hydrogen-test.git – imnotremi Dec 01 '22 at 15:51
  • Oh ok maybe can you provide me more info with the github link ? Because I'm new I'm really strugulling :') – imnotremi Dec 01 '22 at 15:52
  • this won't work as I do not have (and do not want) the credentials to connect to your specific Shopify store. Just in case: PLEASE DON'T SHARE CREDENTIALS HERE. You can however provide us with details on what is inside the `options, selectedVariant, selectedOptions, setSelectedOption` values you get from `useProductOptions` – Xiduzo Dec 01 '22 at 16:13