私は、親コンポーネント(または一般に上位レベルのコンポーネント)が内部子コンポーネントのデータでアクションクリエータをディスパッチできるように、子コンポーネントからいくつかのコンテンツを取り出す必要があります。connect(null、null、null、{withRef:true})が慣習的ではありませんか?
以前は、メソッドデータが必要な親コンポーネントでrefを追跡するのが難しくなっていることがわかってから、this.refs.child.doStuff()
のような子参照の関数を呼び出していました。毎回HOCや他の種類の合成ラッパー私は、私が必要とするチェーン上のrefを渡すために、より多くのコードを追加する必要があります。言うまでもなく、すべての人に標準であった各子関数には重複したコードがたくさんありました。
// child.js
class InnerComponent extends React.PureComponent {
doStuff =() => {
calculateFrom(this.state.content)
// and then do stuff with it..
// I've since made this more redux-y by just returning the data
// out to an action dispatcher
}
}
const SomeHOC = (args) => {
return (Component) => class extends React.Component {
proc(wrappedComponentInstance) {
// I went with using the getWrappedInstance func here
// to mimic conect(.., .., .. { withRef: true }) for
// basic compatibility with a higher level function that
// dives through the wrappedInstances to get to the bottom one
this.getWrappedInstance =() => wrappedComponentInstance;
}
render() {
const props = Object.assign({}, this.props, { ref: this.proc.bind(this) });
return <Component {...props} {...this.state} />
}
}
}
// I actually don't need the connect() here but will on other components of the same style when they're not in their wrapped form
export default connect(..., ..., null, { withRef: true })(SomeHOC()(InnerComponent);
// parent container (there are multiples of these in my app)
class Container extends React.PureComponent {
determineContent = (...) => {
return React.createElement(this.state.content, {
// so I can get to the composited inner element...
ref: (element) => { this._compositeElement = element; },
...viewletProps
});
}
componentWillMount() {
// ...
System.import(`${dynamic}.jsx`).then((content) => {
this.setState({ content });
});
}
renderButtonContainer =() => {
// Here's where things get weird...
if (!this.doStuff) {
this.doStuff = ((() => {
// hook into my ref
const compositeElement = this._compositeElement;
// deep-dive through to get to the base
let base;
if (compositeElement && typeof compositeElement.getWrappedInstance === 'function') {
base = this._compositeElement.getWrappedInstance();
while (typeof base.getWrappedInstance === 'function') {
base = base.getWrappedInstance();
}
if (typeof compositeElement.doStuff === 'function') {
this.doStuff = base.doStuff;
}
}
})());
}
return (
<div hidden={!this.doStuff}>
<span><i class="myIcon" onClick={this.doStuff}></i></span>
</div>
);
}
render() {
<div>
{ this.renderButtonContainer() }
<div>
{ this.determineContent(...) }
</div>
</div>
}
}
ことのすべてを引き出して、今Reduxのスタイルごとにアクションを派遣し、私の減速は、(発生する必要があるもののデータを使用して、すぐに実行だけ同期内部コールを処理せていますので、私はしました私は子コンポーネントが、親コンポーネントの時にまだdoStuff()
(getStuff()
)の呼び出しを返す必要があるので、私は子コンポーネントが必要です。選択すると、私は自分自身の同じrefの問題に立ち往生見つける。
私はこれについてすべて間違っていますか?これは、私の状態モデルの中にgetStuff()
のこの常時変化するデータを格納して、それをコンポーネントに渡す必要がある各子コンポーネントのように思えます。しかし、私はそれが実際のコンポーネントからあまりにも分離していると予想して、私のアプリの残りの部分は本当に気にしません。
子コンポーネントが動的にロードされ、動的にロードされるコンポーネントが、私が探しているメソッドを持っているかもしれないし、持っていないかもしれないので、避けられないと思います。 私が欲しいのは、refのメソッドが利用できる場合は、別のコンポーネントを表示するだけです。 別の問題は、兄弟コンポーネントレベルでこれを行いたいということです。兄弟Aは、兄弟Bのrefと同等の小道具を受け取り、兄弟Bを調べて、そのメソッドが存在するかどうかを調べ、適切な場合は表示することができます。私は "これは正しい方法ではない"と "正しい"方法に関してはごく少数の答えが出てくるのを見ている。 – buddyp450
私のrefプロパティはもちろん、私の兄弟Aコンポーネントには最初の場所で決定を下す必要がある小道具が足りない最初のマウントの後に設定されていません。 – buddyp450
理想的には、 "方法"について心配するべきではありません。あなたは状態に基づいて行動するべきです。おそらく、動的にロードされたコンポーネントが、それがどのようなコンポーネントであるかを報告するアクション(またはコールバックを呼び出す)を送り、それに基づいて親コンポーネントに決定を下させることができます。同様に、「兄弟姉妹」レベルの振る舞いは、通常https://facebook.github.io/react/docs/lifting-state-up.htmlに従って、親に「持ち上げられる」べきである。しかし、一般的には、「リアクションウェイ」は状態を基にUIを動かすことであり、コンポーネントインスタンスと直接対話することはありません。 – markerikson