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

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

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

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

React.js

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

Q&A

解決済

1回答

3748閲覧

useRef で定義した変数の.currentが常にnullになる

donchan777

総合スコア1

JavaScript

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

React.js

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

0グッド

0クリップ

投稿2022/11/02 04:44

課題

React の useRef を使って自分で作成したコンポーネントを親コンポーネントから参照したいのですが、useRefで定義した変数にはnullしか代入されずアクセスできません。

再現コード

npx create-react-app で作成した直後のプロジェクトに、
以下のコンポーネント Test を追加します。

Test.js

js

1const Test = () => { 2 return ( 3 <div> 4 test 5 </div> 6 ) 7} 8export default Test;

Appコンポーネント (Testを 使う側 )で、以下のようにuseRefを定義し、
ボタンを押したときにrefTest変数の中身を確認してみます。

App.js

js

1import { useCallback, useRef } from 'react'; 2import Test from './Test' 3 4function App() { 5 const refTest = useRef(null); 6 7 const onClick = useCallback(() =>{ 8 console.log(refTest.current); 9 }, [refTest]); 10 11 return ( 12 <> 13 <button onClick={onClick}>test</button> 14 <Test ref={refTest}/> 15 </> 16 ); 17} 18export default App;

このとき、コンソールには null が表示されてしまいます。
useCallbackを外したりしましたが、結果は変わりませんでした。

質問

Appから、refTest 変数を使って Test にアクセスしたいのですが、どのようにすればよいでしょうか?

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

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

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

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

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

maisumakun

2022/11/02 05:15

> refTest 変数を使って Test にアクセスしたいのですが 具体的に、Testに対して何をしたいのですが?
donchan777

2022/11/02 11:12

①Testコンポーネント内で定義された関数を、親コンポーネントAppから呼ぶ方法 ②Testコンポーネント内で定義された変数を、親コンポーネントAppから参照・変更する方法 について知りたいです。 回答のコメントの方で、 ①についてはuseImperativeHandleを使って実現する手段を教えていただきました。 ②については先程コメントへの返信で counter を例に質問させていただきました。
guest

回答1

0

ベストアンサー

ふつうに宣言した関数コンポーネントに対して、ref使用できません

関数コンポーネントにはインスタンスがないため、デフォルトでは関数コンポーネントに ref 属性を使用することはできません。(React公式より、強調も原文ママ)

forwardRefを使う必要があります(React公式)。

投稿2022/11/02 05:11

編集2022/11/02 05:13
maisumakun

総合スコア145184

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

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

maisumakun

2022/11/02 05:31

(もっとも、子コンポーネントの状態は、親からpropsを与えて制御するのが一般的なやり方です。単純に内部のエレメントへforwardする場合はともかく、useImperativeHandleを立てる必要のある場合はそうそうありません)
donchan777

2022/11/02 07:17 編集

maisumakunさん ご回答誠にありがとうございます。 もう少しお付き合いお願いできないでしょうか。 例えば、Test コンポーネントが、カーソルを持つエディタコントロールとします。 カーソル位置は編集等で Test内部で変化するため、もしカーソル位置を Test の props にして上位から指定するよう設計してしまうとカーソル位置が固定されてしまうため、Testの内部でカーソル位置を state として持つべきだと考えました。 このとき、App 側からもカーソル位置を変えたいというケースがあり、その場合は Test内に const [pos, setPos] = useState(0); // カーソル位置 const setCursorPos = pos => {setPos(pos);} を用意しておき、 Appから、 refTest.current.setCursorPos( 3 ); のように呼びたかったのです。 ご回答いただいた useImperativeHandle を使ってsetCursorPosを定義して、 Test.jsの末尾で const TestWrapper = React.forwardRef(Test); export default TestWrapper; とエクスポートすることで、Appから refTest.current.setCursorPos( 3 ); のように発行することができました。 さて、やりたいことは実現はできたのですが、 今回のようにAppからカーソル位置を指定したい場合は、 やはり useImperativeHandle を使わなければ実現できないのでしょうか? それとも、他によい(一般的な)方法があるのでしょうか?
maisumakun

2022/11/02 08:30

> 今回のようにAppからカーソル位置を指定したい場合は、 やはり useImperativeHandle を使わなければ実現できないのでしょうか? そうですね、「カーソル位置」や「フォーカス状態」のような、通常Reactで管理していない値の制御はref経由でやって問題ない形です。
donchan777

2022/11/02 10:47 編集

maisumakunさん ご回答ありがとうございます。 > 「カーソル位置」や「フォーカス状態」のような、通常Reactで管理していない値の制御はref経由でやって問題ない形です。 Reactで状態管理できるもの(カウント等の数値など)で 稀にApp(上位)から変更したい、という場合はどのように管理するのがよいのでしょうか? 例えばそれが何かのカウント値だった場合、 ----------------- ・Test クラスのpropsでAppから counter を受け取る ・Test クラスでは、const [countValue, setCountValue] = useState(counter) でカウント値を管理 ・App クラスでは、指定したくなったら props で渡している counter の値を変更する ・Test クラスでは、useEffect 等でcounterの変化をキャッチし setCountValue(counter) を呼ぶ ----------------- という方法しか私には考えられませんでしたが、もっとよい方法があれば教えていただきたいです。 ※追記 上位の方法では ①App が 0に設定 ②Test内部で10になった ③App が 再度0を指定したい というときに、props で指定している counterは 0 → 0 と変化がないのでTestのcountValueは10から変更されませんでした。
maisumakun

2022/11/02 11:58 編集

> Reactで状態管理できるもの(カウント等の数値など)で 稀にApp(上位)から変更したい、という場合はどのように管理するのがよいのでしょうか? 稀にであろうが、親から変えたいものは親の側にstateを持たせる(変更関数も一緒に子へ渡す)のが普通のやり方です。
donchan777

2022/11/02 12:40

親側に持たせるというのは思いつきませんでした。 とても勉強になりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問