質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.39%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

1024閲覧

forwardRef<T, P>のTにuseImperativeHandle用のHandlerとHTMLDivElementの両方を設定する方法

cooper46

総合スコア7

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2021/01/30 01:09

編集2021/01/30 01:11

掲題について、以下の状況で不明なことがあります。

■前提
・子コンポーネント(Child)のDOMにアニメーションを設定
・Child内には任意のタイミングでアニメーションを実行するanimate()関数を実装
・親コンポーネント(Parent)において、Childに対するIntersectionObserverを設定し、交差したタイミングでChild.animate()を実行したい

■問題
上記の場合、Parentからは以下のrefを渡す必要があります。
・IntersectionObserverを設定するためのref(Child.Handler)
Child.animate()を実行するためのref(HTMLDivElement)

ただし、それらのrefはそれぞれ型が異なるため、Child側でTypeErrorが発生してしまいます。
React.forwardRefにおいて、型の異なるrefをどうやったら受け取れるか」というのが今回詰まっている箇所です。

■簡略化したコード

tsx

1// 子コンポーネント 2 3export type Handler = { 4 animate(): void 5} 6 7type Props = { 8 onAnimationEnd(): void 9 ... 10} 11 12export const Child = forwardRef<Handler, Props>((props, ref) => { 13 const { onAnimationEnd } = props 14 15 function animate() { 16 ... 17 } 18 19 useImperativeHandle(ref, () => ({ 20 animate 21 })) 22 23 return ( 24 <div 25 ref={ref} // ←forwardedRef<HTMLDivElement>を受け取らなければいけないのでTypeErrorが発生する 26 className="child" 27 > 28 ... 29 </div> 30 ) 31})

tsx

1// 親コンポーネント 2import { useRef } from 'react' 3import type { Handler } from './Child' 4 5export const Parent = (props) => { 6 const childRef = useRef({} as Handler) 7 8 useEffect(() => { 9 const intersectionObserver = new IntersectionObserver((entries) => { 10 if (entries[0].isIntersecting) { 11 childRef.animate() 12 } 13 }, {...}) 14 intersectionObserver.observe(childRef.current) 15 }, []) 16 17 return ( 18 <> 19 <Child 20 ref={crossRef} 21 /> 22 </> 23 ) 24} 25

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

質問のためにコードを整理していたら気づきました。
そもそもHandleranimate()Childに対するRefを両方設定すれば良いだけでした。

tsx

1// 子コンポーネント 2import { useRef } from 'react' 3import type { RefObject } from 'react' 4 5export type Handler = { 6 animate(): void 7 childRef: RefObject<HTMLDivElement> 8} 9 10type Props = { 11 onAnimationEnd(): void 12 ... 13} 14 15export const Child = forwardRef<Handler, Props>((props, ref) => { 16 const { onAnimationEnd } = props 17 18 function animate() { 19 ... 20 } 21 22 const wrapperRef = useRef<HTMLDivElement>(null) 23 24 useImperativeHandle(ref, () => ({ 25 animate, 26 childRef: wrapperRef 27 })) 28 29 return ( 30 <div 31 ref={wrapperRef} 32 className="child" 33 > 34 ... 35 </div> 36 ) 37})

tsx

1// 親コンポーネント 2import { useRef } from 'react' 3import type { Handler } from './Child' 4 5export const Parent = (props) => { 6 const childRef = useRef({} as Handler) 7 8 // 9 useEffect(() => { 10 const intersectionObserver = new IntersectionObserver((entries) => { 11 if (entries[0].isIntersecting) { 12 childRef.current.animate() 13 } 14 }, {...}) 15 intersectionObserver.observe(childRef.current.wrapperRef.current) 16 }, []) 17 18 return ( 19 <> 20 <Child 21 ref={crossRef} 22 /> 23 </> 24 ) 25}

投稿2021/01/30 01:42

cooper46

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.39%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問