Only 1 true state intro array React js

69 Views Asked by At

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 :)

1

There are 1 best solutions below

0
fxdxpz On BEST ANSWER

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.