[解決済み】React.jsで親コンポーネントにpropsを渡す。
質問
子機の
props
は、React.js で、イベントを使用して親に送信しますか?
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(event) {
// event.component.props ?why is this not available?
},
render: function() {
<Child onClick={this.onClick} />
}
});
入力の値を渡すためにコントロールされたコンポーネントを使うことができるのは知っているが、全部を渡すことができたらいいなと思う。子コンポーネントには、調べたくない情報が含まれていることがあります。
コンポーネントをイベントにバインドする方法があるのでは?
アップデート - 2015年9月1日
1年以上Reactを使ってきて、Sebastien Lorberの回答に触発されて、子コンポーネントを親の関数の引数として渡すことは、次のような結論に達しました。 ではない というのは、Reactのやり方であり、決して良いアイデアではありません。回答を差し替えました。
どのように解決するのか?
編集 : ES6 の更新された例については、最後の例を参照してください。
この回答は、単に直接の親子関係の場合に対応するものです。親と子が多くの仲介者を持つ可能性がある場合、次のことを確認してください。 回答 .
他のソリューションは、ポイントがずれている
しかし、他の回答は非常に重要なことを見逃しています。
<ブロッククオートReact.jsで、イベントを使って子のpropsを親に渡す簡単な方法はないのでしょうか?
親はすでにその子のプロップを持っています! : もし子供がプロップを持っているならば、それは親がそのプロップを子供に提供したからです! 親がすでにプロップを持っているのは明らかなのに、なぜ子が親にプロップを返さなければならないのでしょうか?
より良い実装
子 これ以上複雑にする必要はないのです。
var Child = React.createClass({
render: function () {
return <button onClick={this.props.onClick}>{this.props.text}</button>;
},
});
親と子一人 : 子に渡す値を使って
var Parent = React.createClass({
getInitialState: function() {
return {childText: "Click me! (parent prop)"};
},
render: function () {
return (
<Child onClick={this.handleChildClick} text={this.state.childText}/>
);
},
handleChildClick: function(event) {
// You can access the prop you pass to the children
// because you already have it!
// Here you have it in state but it could also be
// in props, coming from another parent.
alert("The Child button text is: " + this.state.childText);
// You can also access the target of the click here
// if you want to do some magic stuff
alert("The Child HTML is: " + event.target.outerHTML);
}
});
子リストを持つ親 : 親に必要なものがすべて揃っているので、子を複雑にする必要はありません。
var Parent = React.createClass({
getInitialState: function() {
return {childrenData: [
{childText: "Click me 1!", childNumber: 1},
{childText: "Click me 2!", childNumber: 2}
]};
},
render: function () {
var children = this.state.childrenData.map(function(childData,childIndex) {
return <Child onClick={this.handleChildClick.bind(null,childData)} text={childData.childText}/>;
}.bind(this));
return <div>{children}</div>;
},
handleChildClick: function(childData,event) {
alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
alert("The Child HTML is: " + event.target.outerHTML);
}
});
を使用することも可能です。
this.handleChildClick.bind(null,childIndex)
を使用し、その後に
this.state.childrenData[childIndex]
を使用してバインドしていることに注意してください。
null
コンテキストに関連する警告が表示されるからです。
自動バインディング
というシステムです。nullを使うということは、関数のコンテキストを変更したくないということです。
参照
.
他の回答でのカプセル化とカップリングについて
これは私にとっては 悪い カップリングとカプセル化という観点からのアイデアです。
var Parent = React.createClass({
handleClick: function(childComponent) {
// using childComponent.props
// using childComponent.refs.button
// or anything else using childComponent
},
render: function() {
<Child onClick={this.handleClick} />
}
});
プロップの使用 : 上で説明したように、すでに親コンポーネントにpropsがあるので、子コンポーネント全体をpropsにアクセスするために渡すのは無駄です。
参考文献の利用 : イベントにはすでにクリックターゲットがあり、ほとんどの場合、これで十分です。 さらに、子プロセスに直接refを使用することもできます。
<Child ref="theChild" .../>
そして、親の DOM ノードにアクセスするには
React.findDOMNode(this.refs.theChild)
より高度なケースで、親にある子の複数の参照にアクセスしたい場合、子はコールバックで直接すべてのdomノードを渡すことができます。
コンポーネントはインターフェイス (props) を持っており、親は子の内部動作 (内部の DOM 構造や、どの DOM ノードに Ref を宣言するかなど) について何も仮定してはいけません。親が子の参照を使用することは、2 つのコンポーネントを緊密に結合することを意味します。
この問題を説明するために、次のような引用をします。 シャドウDOM ブラウザ内部でスライダーやスクロールバー、ビデオプレーヤーなどのレンダリングに使用されます。
<ブロッククオートウェブ開発者が到達できる範囲に境界を作ったのです。 実装の詳細とみなされ、アクセスできないもの。 ということです。しかし、ブラウザはこの境界を自由に行き来することができます。 この境界があることで、彼らはすべてのHTML要素を構築することができました divやspanから、昔ながらのWeb技術を使って と同じように。
問題は、子の実装の詳細を親に漏らすと、親に影響を与えずに子をリファクタリングすることが非常に困難になることです。つまり、ライブラリの作者として(あるいはShadow DOMを使うブラウザのエディタとして)、これは非常に危険なことです。
もしChromeがスクロールバーを実装して、クライアントがそのスクロールバーの内側のdomノードにアクセスできるようにしていたら、クライアントがそのスクロールバーを簡単に壊す可能性があることを意味し、Chromeがスクロールバーのリファクタリング後に自動アップデートを実行すると、アプリはより簡単に壊れてしまいます......。その代わり、CSSでスクロールバーの一部をカスタマイズするような安全なものへのアクセスしか与えません。
その他の使用について
コールバックでコンポーネント全体を渡すのは危険です。
childComponent.setState(...)
または
childComponent.forceUpdate()
また、親の内部で新しい変数を代入することで、アプリ全体の推論が難しくなります。
編集:ES6の例
現在、多くの人がES6を使用しているため、以下はES6構文用の同じ例です。
子はとてもシンプルでいい。
const Child = ({
onClick,
text
}) => (
<button onClick={onClick}>
{text}
</button>
)
親はクラスでもいいし(最終的にはそれ自身で状態を管理できるが、ここではpropsとして渡している)。
class Parent1 extends React.Component {
handleChildClick(childData,event) {
alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
alert("The Child HTML is: " + event.target.outerHTML);
}
render() {
return (
<div>
{this.props.childrenData.map(child => (
<Child
key={child.childNumber}
text={child.childText}
onClick={e => this.handleChildClick(child,e)}
/>
))}
</div>
);
}
}
しかし、状態を管理する必要がなければ、簡素化することも可能です。
const Parent2 = ({childrenData}) => (
<div>
{childrenData.map(child => (
<Child
key={child.childNumber}
text={child.childText}
onClick={e => {
alert("The Child button data is: " + child.childText + " - " + child.childNumber);
alert("The Child HTML is: " + e.target.outerHTML);
}}
/>
))}
</div>
)
PERF警告
(ES5/ES6に適用): もし、あなたが
PureComponent
または
shouldComponentUpdate
を使用するため、上記の実装はデフォルトでは最適化されません。
onClick={e => doSomething()}
レンダリングフェーズで直接バインドすると、親がレンダリングするたびに新しい関数が作成されるからです。これがアプリのパフォーマンス上のボトルネックになっている場合は、データを子に渡し、それを "stable" コールバック(親クラスで設定し、バインドして
this
を使用し、クラスのコンストラクタで
PureComponent
の最適化を行うか、あるいは、独自の
shouldComponentUpdate
で、props比較チェックのコールバックは無視します。
を使用することもできます。 再コンポジット ライブラリは、高次のコンポーネントを提供し、きめ細かな最適化を実現します。
// A component that is expensive to render
const ExpensiveComponent = ({ propA, propB }) => {...}
// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedComponent = pure(ExpensiveComponent)
// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedComponent = onlyUpdateForKeys(['propA', 'propB'])(ExpensiveComponent)
この場合、Childコンポーネントを使用することで最適化することができます。
const OptimizedChild = onlyUpdateForKeys(['text'])(Child)
関連
-
[解決済み】node.js TypeError: path must be absolute or specify root to res.sendFile [JSONのパースに失敗しました]。
-
[解決済み】JavaScriptのボタンonclickが機能しない
-
[解決済み】React.jsの配列の子要素のユニークキーを理解する
-
[解決済み】 Uncaught Error: Invariant Violation: 解決済み】 Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function but got: object.
-
[解決済み】Syntax error: JavaScriptの不正なreturnステートメント
-
[解決済み] Node.jsのプログラムにコマンドライン引数を渡すにはどうしたらいいですか?
-
[解決済み] 親メソッドから子メソッドを呼び出す
-
[解決済み] react-router - ハンドラコンポーネントにpropsを渡す
-
[解決済み】 {this.props.children} に props を渡すには?}
-
[解決済み】ReactのonClick関数はレンダリング時に発火する
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】XMLHttpRequestモジュールが定義されていない/見つからない
-
[解決済み】NodeJS "ESモジュールをロードするためにインポートを使用する必要があります。"
-
[解決済み】Javascriptのコールバック関数がFirefoxで「Callback is not a function」というエラーを投げる
-
[解決済み】BootstrapのCollapseが折りたたまれない
-
[解決済み】React、Uncaught ReferenceError。ReactDOMは定義されていません
-
[解決済み】Redux TypeError: 未定義のプロパティ 'apply' を読み取れない
-
[解決済み】TypeError:res.jsonは関数ではありません。
-
[解決済み】TypeError: AngularJSで未定義のプロパティ'get'を読み取れない
-
[解決済み】 \u003C とは何ですか?
-
[解決済み】ReactJS 2つのコンポーネントが通信しています。