[解決済み】フォーム要素の状態を兄弟/親要素に渡す正しい方法とは?
質問
- ReactのクラスPがあり、C1とC2という2つの子クラスをレンダリングしているとします。
- C1には入力フィールドがあります。この入力フィールドをFooと呼ぶことにする。
- 私の目標は、Fooの変更にC2が反応するようにすることです。
2つの解決策を思いついたのですが、どちらもいまいちしっくりきません。
第一の解決策
-
Pに状態を割り当てる。
state.input
. -
を作成します。
onChange
この関数は、イベントを取り込んでstate.input
. -
これを渡す
onChange
としてC1へ渡す。props
を、C1 にバインドさせます。this.props.onChange
をonChange
をFooの
これは動作します。Fooの値が変わるたびに、その値をトリガーとして
setState
を生成し、P は C2 に渡す入力を得ることができます。
しかし、同じ理由で、子要素から親要素の状態を設定するのは、どうもしっくりこない。これは、Reactの設計方針である「単一方向のデータフロー」を裏切っているように思えます。
それとも、もっとReactらしい解決策があるのでしょうか?
第二の解決策
PにFooを入れればいいんです。
しかし、これはアプリを構成する際に従うべき設計原則なのでしょうか。すべてのフォーム要素を
render
は、最上位クラスのものですか?
この例のように、C1を大量にレンダリングする場合、すべてのC1ファイルに
render
のC1を
render
を、C1がform要素を持っているというだけで、Pの
どうすればいいのでしょうか?
どのように解決するのですか?
つまり、私が正しく理解していれば、最初の解決策は、ルート・コンポーネントに状態を保持していることを示唆しているのですね?私はReactの制作者について語ることはできませんが、一般的に、これは適切な解決策だと思います。
状態の維持は、Reactが作られた理由のひとつです(少なくとも私はそう考えています)。もしあなたが、相互に依存する多くの可動部分を持つ動的なUIを扱うために、クライアント側で独自のステートパターンを実装したことがあるなら、Reactを好きになるでしょう。
ルートコンポーネントのイベントに応答しているだけで、双方向バインディングでデータを取得しているわけではありません。ルートコンポーネントに「ちょっと、ここで何か起きたから値を調べてみて」と伝えるか、子コンポーネントのデータの状態を渡して状態を更新しているのです。C1で状態を変更し、C2にそれを認識させたい場合、ルートコンポーネントで状態を更新して再レンダリングすると、ルートコンポーネントで状態が更新されて渡されたため、C2のプロップは同期されます。
class Example extends React.Component {
constructor (props) {
super(props)
this.state = { data: 'test' }
}
render () {
return (
<div>
<C1 onUpdate={this.onUpdate.bind(this)}/>
<C2 data={this.state.data}/>
</div>
)
}
onUpdate (data) { this.setState({ data }) }
}
class C1 extends React.Component {
render () {
return (
<div>
<input type='text' ref='myInput'/>
<input type='button' onClick={this.update.bind(this)} value='Update C2'/>
</div>
)
}
update () {
this.props.onUpdate(this.refs.myInput.getDOMNode().value)
}
})
class C2 extends React.Component {
render () {
return <div>{this.props.data}</div>
}
})
ReactDOM.renderComponent(<Example/>, document.body)
関連
-
[解決済み】無効な設定オブジェクトです。APIスキーマと一致しない設定オブジェクトを使用してWebpackが初期化されました。
-
[解決済み】Reactコンポーネント内でswitchステートメントを使用するには?
-
[解決済み] バベルエラーです。JSX値は、式または引用されたJSXテキストのいずれかである必要があります。
-
[解決済み] マテリアルUIセレクトフィールドのマルチセレクト
-
[解決済み] SVGサークル内の画像にボーダーを追加する方法
-
[解決済み] React TypeScriptで作業しているときに、Jestが予期しないトークンに遭遇した
-
[解決済み] ReactJs "インバリアント違反..." リアクトの古典的な問題
-
[解決済み] 拡張子.tsと.tsxの違いは何ですか?どちらもreactのタイプスクリプトファイルの拡張子として使用されます。では、どこで使うべきなのでしょうか?
-
[解決済み】React:setStateを使用してstateのstate.item[1]を更新するには?
-
[解決済み】React Formでpropsが変更されたときに状態を更新する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンポーネントの定義に表示名がない react/display-name
-
[解決済み】Reactでclsxを使用する方法
-
[解決済み] テスト
-
[解決済み] error 'document' is not defined : eslint / React
-
[解決済み] TypeError: reactjs の未定義のプロパティ 'status' を読み取ることができません。
-
[解決済み] Uncaught (in promise) Error: リクエストに失敗、ステータスコード404
-
[解決済み] componentWillReceiveProps は名称が変更されました。
-
[解決済み] React TypeScriptで作業しているときに、Jestが予期しないトークンに遭遇した
-
[解決済み] プロップ `history` は `Router` で必須とマークされているが、その値は `undefined` である。
-
[解決済み】Reactで子の状態にアクセスする方法