import React, { useCallback, useEffect, useReducer, useRef } from 'react'; import { MdArrowBack, MdArrowForward } from 'react-icons/md' export function throttle(callback, limit) { let handler = null; // Initially, we're not waiting return (...args) => { // We return a throttled function if (!handler) { // If we're not waiting callback(...args); // Execute users function handler = setTimeout(() => handler = null, limit); } } } function debounce(callback, delay) { let handler = null; return (...args) => { clearTimeout(handler); handler = setTimeout(() => callback(...args), delay); } } const transTime = 200 const elastic = `transform ${transTime}ms cubic-bezier(0.4, 0.0, 0.2, 1)`; function reducer(state, action) { switch (action.type) { case 'set-rect': return { ...state, rect: action.rect }; case 'resize': return { ...state, rect: action.rect, dragLeft: state.pg * action.rect.width, dragging: true }; case 'move': return { ...state, pg: state.pg + action.del, dragging: false }; case 'drag-start': return { ...state, dragLeft: state.pg * state.rect.width, dragging: true }; case 'drag': return { ...state, dragLeft: state.dragLeft - action.move }; case 'drag-end': return { ...state, pg: Math.round(state.dragLeft / state.rect.width), dragging: false }; default: console.log('wtf') console.error(action) } } export const Carousel = () => { const arr = [1, 2, 3] const ref = useRef(null) const [state, dispatch] = useReducer(reducer, { rect: {}, pg: 0, dragLeft: 0, dragging: false }) useEffect(() => { dispatch({ type: 'set-rect', rect: ref.current.getBoundingClientRect() }) }, [ref]) const updateSize = useCallback( debounce( () => { dispatch({ type: 'resize', rect: ref.current.getBoundingClientRect() }) } , 200 ) , [] ) useEffect(() => { window.addEventListener('resize', updateSize) }, []) return <>