React Hooks Example: Timer

Simple React Hooks example. A timer that pauses when you hold the mouse button. Creates and uses a custom Hook.

HTML

<div id="app"></div>

SCSS

.carousel-wrapper {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
  margin-bottom: 0.5rem;
  height: 8rem;

  .arrow {
    height: fit-content;
    align-self: center;
  }

  .items-wrapper {
    display: grid;
    grid-template-columns: repeat(4, 2.5rem);
    gap: 1rem;
  margin: auto 0;

    .item {
      display: flex;
      justify-content: center;
      align-items: center;
      position: relative;
      box-shadow: 0px 4px 4px rgba(46, 37, 37, 0.15), 0px 0px 10px 1px rgba(203, 205, 208, 0.3);
      border-radius: 4px;
      padding: 0.5rem;
      height: 2.5rem;
      
      &.is-hidden {
        visibility: hidden;
      }
    }
  }
}

React

const items = [
  { id: 1 },
  { id: 2 },
  { id: 3 },
  { id: 4 },
  { id: 5 },
  { id: 6 },
  { id: 7 },
  { id: 8 },
  { id: 9 },
  { id: 10 },
  { id: 11 },
  { id: 12 },
  { id: 13 },
  { id: 14 },
  { id: 15 },
  { id: 16 },
];

function isDisplayedItem(index, displayedSlice) {
  return index >= displayedSlice.start && index < displayedSlice.end;
}

const Carousel = () => {
  const [displayedSlice, setDisplayedSlice] = React.useState({
    start: 0,
    end: 8,
  });
  
  const itemsPerSlide = 8;

  return (
    <div className="carousel-wrapper">
      <button
        className="arrow"
        disabled={displayedSlice.start === 0}
        onClick={() =>
          setDisplayedSlice((currentSlice) => ({
            start: currentSlice.start - itemsPerSlide,
            end: currentSlice.end - itemsPerSlide,
          }))
        }
      >
        -
      </button>
      <div className="items-wrapper">
        {items.map((item, index) => (
          <div
            key={index}
            className={`item ${
              !isDisplayedItem(index, displayedSlice) ? "is-hidden" : ""
            }`}
          >
            {index}
          </div>
        ))}
      </div>
      <button
        className="arrow"
                disabled={displayedSlice.end > items.length - 1}
        onClick={() =>
          setDisplayedSlice((currentSlice) => ({
            start: currentSlice.start + itemsPerSlide,
            end: currentSlice.end + itemsPerSlide,
          }))
        }
      >
        +
      </button>
    </div>
  );
};

ReactDOM.render(<Carousel />, document.querySelector("#app"));