target
ステートを変更した時の副作用として、target.id
を持つ要素までスクロールする機能を作る。
useRef
を使用せず、idを使用した方が単純だったので、idを使用している。
(特に調査はしていない。)
// ⚠️ target と item は同じデータ構造 useEffect(() => { if (!target) { return } const targetEl = document.getElementById(target?._id) const containerEl = document.getElementById('container') const targetTop = targetEl?.getBoundingClientRect().top || 0 const containerTop = containerEl?.getBoundingClientRect().top || 0 const containerScrollTop = containerEl?.scrollTop || 0 const marginTop = 36 // 👈 スクロールの位置36px下に調整する const scrollSize = targetTop - containerTop + containerScrollTop - marginTop containerEl?.scrollTo({ top: scrollSize, behavior: 'smooth' }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [target])
<div className="container overflow-y-auto"> {items.map((item, index) => ( <div id={item.id}> {item.name} </div> ))} </div>
scroll-padding
をという便利なcssプロパティがあったので使用したら、スッキリした。
scroll-padding - CSS: カスケーディングスタイルシート | MDN
また、スクロールさせるコンテナのidも消すことができた。
useEffect(() => { if (!target) { return } const targetEl = document.getElementById(target?._id) targetEl?.scrollIntoView({ behavior: 'smooth' }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [target])
// ⚠️ overflow-y-autoは必須 <div className="scroll-py-[36px] overflow-y-auto"> {items.map((item, index) => ( <div id={item.id}> {item.name} </div> ))} </div>