Paweł
Paweł

Reputation: 73

Problem with using different onClick events in one button component

I wanted to make my components as reusable as it possible but when I started adding events the problems occured. I am using one button component in a lot of places in my app and I just change its name. It worked fine when I passed one onClick event to it (to change menu button name) but when I wanted to do the same with another button (to change cycle name) and when I passed second onClick event to the same button component the menu button stopped working. I tried to find solution but found only different topics. I know I could make a wrapper around the button and make onClick on the wrapper, but I think I am doing something wrong and there must be more elegant way to handle this.

Button component

export const Button = ({text, changeButtonName, changeCycle}) => {

  return (
    <AppButton onClick={changeButtonName, changeCycle}>
      {text}
    </AppButton>
  );
};

Navbar component where cycle and menuu buttons are placed

export const Navbar = () => {

  const menuButton = 'Menu';
  const closeButton = 'Zamknij';

  const [menuButtonName, setMenuButtonName] = useState(menuButton);

  const changeButtonName = () => {
    menuButtonName === menuButton ? setMenuButtonName(closeButton) : setMenuButtonName(menuButton);
  }

  const interiorButton = 'Interior →';
  const structuralCollageButton = 'Structural Collage →';

  const [cycleButtonName, setCycleButtonName] = useState(interiorButton);

  const changeCycle = () => {
    cycleButtonName === interiorButton ? setCycleButtonName(structuralCollageButton) : setCycleButtonName(interiorButton);
  }

  return (
    <Nav>
      <AuthorWrapper>
        <AuthorName>
          Michał Król
        </AuthorName>
        <AuthorPseudonym>
          Structuralist
        </AuthorPseudonym>
      </AuthorWrapper>
      <CycleButtonWrapper >
        <Button text={cycleButtonName} changeCycle={changeCycle} />
      </CycleButtonWrapper>
      <MenuButtonWrapper>
        <Button text={menuButtonName} changeButtonName={changeButtonName} />
      </MenuButtonWrapper>
    </Nav>
   )
}

Upvotes: 1

Views: 1046

Answers (3)

buzatto
buzatto

Reputation: 10382

this is not a really reusable approach for a Button. For every new method name you would have to include in the props params and you could face something like:

export const Button = ({text, changeButtonName, changeCycle, changeTheme, changeDisplay})

the proper way to make it reusable would be by passing only one handler to your button:

export const Button = ({text, clickHandler}) => {

  return (
    <AppButton onClick={clickHandler}>
      {text}
    </AppButton>
  );
};

fwiw, the reason you have problem is because at this code onClick={changeButtonName, changeCycle} you are passing multiple expressions with comma operator where the last operand is returned.

Upvotes: 2

Arfan ali
Arfan ali

Reputation: 439

update your code like

<AppButton onClick={()=> {
  changeButtonName && changeButtonName();
  changeCycle && changeCycle();
 }}>
  {text}
</AppButton>

Upvotes: 0

Shubhaw Kumar
Shubhaw Kumar

Reputation: 721

You cannot pass two functions to onClick. Either do a conditional check that call that function which is passed or make a wrapper function.

export const Button = ({text, changeButtonName, changeCycle}) => {

  return (
    <AppButton onClick={changeButtonName || changeCycle}>
      {text}
    </AppButton>
  );
};

or

export const Button = ({text, changeButtonName, changeCycle}) => {

  return (
    <AppButton
        onClick={() => {
          changeButtonName && changeButtonName();
          changeCycle && changeCycle();
        }
    }>
      {text}
    </AppButton>
  );
};

Upvotes: 0

Related Questions