Custom Hook
seconds elapsed
説明
カスタムフックのサンプルコード
補足
- カスタムフックは、ファイル名を use から始める必要がある。 e.g. useTimer etc
利用するshadcn/uiコンポーネント
- button
サンプルコード
Example.tsx
'use client'; import { Button } from '@repo/ui'; import { useState } from 'react'; import useTimer from './_hooks/useTimer'; const Example = () => { const [isDisplayed, setIsDisplayed] = useState(true); return ( <div className="flex flex-col place-items-start gap-4"> {isDisplayed && <Timer />} <Button className="my-2" onClick={() => setIsDisplayed((prev) => !prev)}> {isDisplayed ? 'Not Displayed' : 'Displayed'} </Button> </div> ); }; const Timer = () => { const { time, isRunning, toggle, reset } = useTimer(); return ( <> <h3> <time>{time}</time> <span> seconds elapsed</span> </h3> <div className="flex gap-2"> <Button onClick={toggle}>{isRunning ? 'Pause' : 'Start'}</Button> <Button onClick={reset}>Reset</Button> </div> </> ); }; export { Example };
useTimer.ts
import { useEffect, useLayoutEffect, useState } from 'react'; const useTimer = () => { const [time, setTime] = useState(0); const [isRunning, setIsRunning] = useState(false); useLayoutEffect(() => { const _time = parseInt(window.localStorage.getItem('time-key') ?? ''); if (!isNaN(_time)) { setTime(_time); } }, []); useEffect(() => { console.log('init'); let intervalId: number | undefined = undefined; if (isRunning) { intervalId = window.setInterval(() => { console.log('timer start'); setTime((prev) => prev + 1); }, 1000); } return () => { window.clearInterval(intervalId); console.log('end'); }; }, [isRunning]); useEffect(() => { // console.log('updated'); const _time = parseInt(window.localStorage.getItem('time-key') ?? ''); if (time === 0 && !isNaN(_time)) { return; } document.title = 'counter: ' + time; window.localStorage.setItem('time-key', time.toString()); return () => { // console.log('updated end'); }; }, [time]); const toggle = () => { setIsRunning((prev) => !prev); }; const reset = () => { setIsRunning(false); setTime(0); window.localStorage.setItem('time-key', '0'); }; return { time, isRunning, toggle, reset, }; }; export default useTimer;