0

What's up ?

I'm trying to reproduce the sliding button effect from frontity home page with ReactJS (NextJS). Sliding buttons from Frontity

I managed to create the sliding button effect BUT I'm struggling with state management. I have all my objects mapped with a "isActive : true/false" element and I would to create a function that put "isActive : true" on the clicked button BUT put "isActive: false" on all the other buttons. I don't know the syntax / method for that kind of stuff.

Please, take a look at my codesandbox for more clarity (using react hooks): https://codesandbox.io/s/busy-shirley-lgx96

Thank you very much people :)

Kas Elvirov
  • 7,394
  • 4
  • 40
  • 62
  • 1
    You are mapping the buttons by index, and appear to be using the index as part of the logic to update buttons... why not just store the "active index" and check in the render `isActive={index === activeIndex}`? – Drew Reese Oct 28 '20 at 07:54

1 Answers1

0

UPDATE: As pointed out above by Drew Reese, even more cleaner/easier is to have just one activeIndex state:

const TabButtons = () => {
  const [activeIndex, setActiveIndex] = useState(0);

  const handleButtonClick = (index) => {
    setActiveIndex(index);
  };

  return (
    <>
      <ButtonsWrapper>
        {TabButtonsItems.map((item, index) => (
          <div key={item.id}>
            <TabButtonItem
              label={item.label}
              ItemOrderlist={item.id}
              isActive={index === activeIndex}
              onClick={() => handleButtonClick(index)}
            />
          </div>
        ))}
        <SlidingButton transformxbutton={activeIndex}></SlidingButton>
      </ButtonsWrapper>
    </>
  );
};

I have made a slight modification of your TabButtons:

const TabButtons = () => {
  const [buttonProps, setButtonProps] = useState(TabButtonsItems);

  // ////////////   STATE OF SLIDING BUTTON (TRANSLATE X )  ////////////

  const [slidingbtn, setSlidingButton] = useState(0);

  // //////////// HANDLE CLIK BUTTON  ////////////

  const HandleButtonState = (item, index) => {
    setButtonProps((current) =>
      current.map((i) => ({
        ...i,
        isActive: item.id === i.id
      }))
    );

    setSlidingButton(index);
  };

  return (
    <>
      <ButtonsWrapper>
        {buttonProps.map((item, index) => (
          <div key={item.id}>
            <TabButtonItem
              label={item.label}
              ItemOrderlist={item.id}
              isActive={item.isActive}
              onClick={() => HandleButtonState(item, index)}
            />
          </div>
        ))}
        <SlidingButton transformxbutton={slidingbtn}></SlidingButton>
      </ButtonsWrapper>
    </>
  );
};

When we click on a button, we set its isActive state to true and all the rest buttons to isActive: false. We also should use state, since we also declared it. Changing state will force component to re-render, also we are not mutating anything, but recreating state for buttons.

fxdxpz
  • 1,969
  • 17
  • 29