Home > Net >  How to select only one button with React Typescript?
How to select only one button with React Typescript?

Time:06-29

So I have created a group of three buttons where you can select the size of the pizza, the problem is that all three buttons are the same so when I click one, all of them activate. How can I make so that only the button that is clicked is activated?

Code:

/** @jsxImportSource @emotion/react */
import React, { useState } from 'react';
import styles from './PizzaSize.styles';
export const PizzaSize: React.FC = () => {
  const [selected, setSelected] = useState<boolean>(false);
  const clickHandler = () => {
    setSelected(!selected);
  };
  return (
    <div css={styles.pizza__size__selector}>
      <button
        id="1"
        css={
          selected
            ? [styles.pizza__size__btn, styles.pizza__size__btn__selected]
            : styles.pizza__size__btn
        }
        onClick={clickHandler}
      >
        S
      </button>
      <button
        id="2"
        css={
          selected
            ? [styles.pizza__size__btn, styles.pizza__size__btn__selected]
            : styles.pizza__size__btn
        }
        onClick={clickHandler}
      >
        M
      </button>
      <button
        id="3"
        css={
          selected
            ? [styles.pizza__size__btn, styles.pizza__size__btn__selected]
            : styles.pizza__size__btn
        }
        onClick={clickHandler}
      >
        L
      </button>
    </div>
  );
};

CodePudding user response:

You could save the string ('S', 'M', 'L') instead of a boolean, and then in each css prop, check if selected equals the corresponing letter.

Like in the following example

import React, { useState } from 'react';
import styles from './PizzaSize.styles';
export const PizzaSize: React.FC = () => {
  const [selected, setSelected] = useState<string>('');

  // Set or reset the selected size
  const setSelectedSize = (size: string) => {
      if (!selected) setSelected(size);
      else setSelected(''); // Reset if click on active button
  }

  return (
    <div css={styles.pizza__size__selector}>
      <button
        id="1"
        css={
          selected === 'S'
            ? [styles.pizza__size__btn, styles.pizza__size__btn__selected]
            : styles.pizza__size__btn
        }
        onClick={() => setSelectedSize('S')}
      >
        S
      </button>
      <button
        id="2"
        css={
           selected === 'M'
            ? [styles.pizza__size__btn, styles.pizza__size__btn__selected]
            : styles.pizza__size__btn
        }
        onClick={() => setSelectedSize('M')}
      >
        M
      </button>
      <button
        id="3"
        css={
          selected === 'L'
            ? [styles.pizza__size__btn, styles.pizza__size__btn__selected]
            : styles.pizza__size__btn
        }
        onClick={() => setSelectedSize('L')}
      >
        L
      </button>
    </div>
  );
};

CodePudding user response:

I optimized your code, when your code is repeating you have to generalize it, you can make a separate component or you can do as you see in the code below, you need to use a unique key (index) to show Button active, as I use the index and pass the index to the clickHandler function. I hope this would be helpful. Thanks

/** @jsxImportSource @emotion/react */
import React, { useState } from 'react';
import styles from './PizzaSize.styles';
export const PizzaSize: React.FC = () => {
  const [selected, setSelected] = useState(null);
  const clickHandler = (index) => {
    setSelected(index);
  };

  const data = [
    {
      id: "1",
      name: "S"
    },
    {
      id: "2",
      name: "M"
    },
    {
      id: "3",
      name: "L"
    },
  ]

  return (
    <div css={styles.pizza__size__selector}>
      {data.map((item, index) => (
        <button
          id={item.id}
          css={
            selected === index
              ? [styles.pizza__size__btn, styles.pizza__size__btn__selected]
              : styles.pizza__size__btn
          }
          onClick={() => clickHandler(index)}
        >
          {item.name}
        </button>
      ))}
    </div>
  );
};
  • Related