やりたいこと
ReactでコンポーネントAからコンポーネントB内のメソッドを呼び出したいです。
クラスコンポーネントの場合は以下のように実装できるはずですが、
同じことを関数コンポーネント間で行うにはどのような方法が良いのでしょうか?
実際のコンポーネントBはhookで状態管理を行っており、コンポーネントAに返したい値は'hoge'のような固定メッセージではなくB内のstateによって動的に変化させたいです。
そうなってくると、やはりクラスコンポーネントを使用するのが最もシンプルでしょうか?
クラスコンポーネントの実装例
コンポーネントA
javascript
1import B from 'B' 2 3class A extends React.Component { 4 getMessage(){ 5 const message = B.returnMessage() 6 return message 7 } 8render(){ 9 return( 10 { getMessage() } // 'hoge' 11 } 12 } 13}
コンポーネントB
javascript
1class B extends React.Component { 2 static returnMessage(){ 3 return 'hoge' 4 } 5} 6export default B
「クラスコンポーネントの実装例」の方ですが、本当にnew Bのように書いているのですか?
すみませんまぎらわしかったです。実際にはインスタンス化してないです。
共通の親コンポーネントに状態を持たせればいいと思います。
(そもそもクラスとインスタンスの区別がついてない疑惑がありますね…。)
クラスとインスタンスの区別はついているつもりです。
上に書いた例が悪かったです。質問内容に沿ったものではありませんでした。忘れてください。。
---
input要素を含んだBで入力された文字列から、リアルタイムにAで画像生成する機能を作っています。
(AはBの親ではなく、ただBの文字列だけ利用したい)
・AとBをラップしたコンポーネントCでstateを管理
・Cでcontextを作成し、stateをAとBに渡す
・AとBの処理中でstateの変更をしたい時は、Cのstateを変更する
元々このように関数コンポーネントで書いていたのですが、「クラスコンポーネントの実装例」に書いたような、直接Bのメソッドを呼びだすやり方の方がシンプルに実現できるのでは?と思い質問をしました。
つまり、
・AとBは各々でstateを管理
・クラスBの中に動的にstateを返すメソッドを書く
・Aからそのメソッドを叩く(この時Bをインスタンス化しないです)
こうすれば、CでABで扱うstateを管理したりcontextを作成せずに済むのでより良いではと思ったのですが、これを関数コンポーネントで実現するベストな方法が分からなかったので質問させていただきました。
C で const [value, setValue] = useState(); して、A に value、B に value と setValue を渡すだけです。
おっしゃっている意味はわかるのですが、
実際には、A→A1→A2...、B→B1→B2...のような階層構造によくなりますよね?
B2でsetValueされた値をA2で扱いたい時にバケツリレーになって不便に感じてしまいます。
(contextを使うことで省略できますが)
それよりもA2からB2のメソッドを直接呼んで欲しい値を入手すればいい、という発想は何か間違っていますでしょうか?
子のstateを親が管理するメリットをちゃんと理解できていないのかもしれません。
階層が深くなるなら context などを使いたくなるのは分かります。
React では、A2 から B2 を直接参照するための方法は基本的に提供されていないと認識しています。
(もちろん、グローバル変数などを使って無理やりやればできるでしょうけど。)
また、A2 が B2 を参照し、B2 は C3 を参照し、C3 は A2 を参照し…、ということをやり始めたらキリがないですからね。React の思想として、データの流れを一方向にすると言うのがあって、それに反していると思います。
>React の思想として、データの流れを一方向にすると言うのがあって、それに反していると思います。
なるほど...それは確かに反していますね。。。
stateはコンポーネントが各自で管理して、受け渡ししたい値がある時だけ独自にメソッドを書けばいいという考え方で作ってました。そもそも根本の思想から間違えていたということですね。
いやぁ、それにしても状態管理の設計難しいです...
遅い時間まで付き合っていただきありがとうございます!
回答1件
あなたの回答
tips
プレビュー