Upgrade to Pro — share decks privately, control downloads, hide ads and more …

useImperativeHandleで理解する クロージャと評価タイミング

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

useImperativeHandleで理解する クロージャと評価タイミング

Avatar for Tasuku Watanabe

Tasuku Watanabe

January 07, 2026
Tweet

More Decks by Tasuku Watanabe

Other Decks in Programming

Transcript

  1. useImperativeHandleを使ったコンポーネント const VideoPlayer = ({ src, ref }) => {

    const videoRef = useRef<HTMLMediaElement>(null) useImperativeHandle(ref, () => ({ get currentTime() { return videoRef.current?.currentTime // 動画の再生位置 } }), []) return <video ref={videoRef} src={src} /> } DOMへの直接アクセスを隠蔽し、必要な機能だけを公開 2
  2. 親コンポーネントでの使用 const ParentComponent = () => { const parentRef =

    useRef<VideoPlayerRef>(null) const handleClick = () => { parentRef.current?.currentTime // アクセス可能 parentRef.current?.duration // アクセス不可 } return ( <> <VideoPlayer src="video.mp4" ref={parentRef} /> <button onClick={handleClick}>クリック</button> </> ) } 公開するプロパティとメソッドを子コンポーネント側で制限している 3
  3. NG例①:プロパティの値を変数に代入する useImperativeHandle(parentRef, () => { const currentTime = videoRef.current?.currentTime //

    0 const volume = videoRef.current?.volume // 1 return { get currentTime() { return currentTime }, // 0で固定される get volume() { return volume }, // 1で固定される } }, []) 問題: useImperativeHandle実行時に値が評価され、クロージャに固定される → 変数に代入した時点で値がコピーされるため、動画が再生されても更新されない 5
  4. NG例②:DOMへの参照を変数に代入する useImperativeHandle(parentRef, () => { const video = videoRef.current return

    { get currentTime() { return video?.currentTime }, get volume() { return video?.volume }, } }, []) 問題: DOMのマウントが未完了だと、クロージャによって const video = null がキャプチ ャされ、DOMマウント完了後も変数は null のままになる ※ 条件付きレンダリングや遅延マウントなどで発生する可能性 6
  5. 解決策:getter内でrefを直接参照 useImperativeHandle(parentRef, () => ({ get currentTime() { return videoRef.current?.currentTime

    }, get volume() { return videoRef.current?.volume } }), []) 変数に代入せず、getter内で毎回 videoRef.current を参照 → getter呼び出し時に評価されるため、最新の値を取得でき、マウントタイミングに も依存しない 7