2017-07-22 9 views
0

私は、親コンポーネント(または一般に上位レベルのコンポーネント)が内部子コンポーネントのデータでアクションクリエータをディスパッチできるように、子コンポーネントからいくつかのコンテンツを取り出す必要があります。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()のこの常時変化するデータを格納して、それをコンポーネントに渡す必要がある各子コンポーネントのように思えます。しかし、私はそれが実際のコンポーネントからあまりにも分離していると予想して、私のアプリの残りの部分は本当に気にしません。

答えて

1

確かに、なしはまったくいい考えのようです。技術的に可能であっても、ReactとReduxの両方の意図された使用法に完全に反します。

参考文献は一般的にエスケープハッチであり、必要な場合にのみ使用してください。クリックがDOMノード内にあるかどうかを判断する、または制御されない入力から値を読み取るなどの操作が必要な場合があるため、DOMノードへの参照がより便利です。コンポーネントの使用例が大幅に少なくなっています。特に、コンポーネントのメソッドを直接呼び出すことは、間違いなく慣用的なリアクションの使用であり、可能な限り避けるべきです。そこから、Reactの実装の要領にうっとりして、本当に悪い考えです。

親コンポーネント内のネストされた子データを使用する必要があり、それらが広く分離されている場合は、それらの子を介して何らかのコールバック・プロップを渡すか、Reduxアクションをそのデータをストアに入れ、親にそのデータをサブスクライブします。

だから、その記述とサンプルコードから実際に何が必要なのかを正確に伝えるのは難しいですが、あなたが持っているものは正しい方法ではないと言うことはできます。

+0

子コンポーネントが動的にロードされ、動的にロードされるコンポーネントが、私が探しているメソッドを持っているかもしれないし、持っていないかもしれないので、避けられないと思います。 私が欲しいのは、refのメソッドが利用できる場合は、別のコンポーネントを表示するだけです。 別の問題は、兄弟コンポーネントレベルでこれを行いたいということです。兄弟Aは、兄弟Bのrefと同等の小道具を受け取り、兄弟Bを調べて、そのメソッドが存在するかどうかを調べ、適切な場合は表示することができます。私は "これは正しい方法ではない"と "正しい"方法に関してはごく少数の答えが出てくるのを見ている。 – buddyp450

+0

私のrefプロパティはもちろん、私の兄弟Aコンポーネントには最初の場所で決定を下す必要がある小道具が足りない最初のマウントの後に設定されていません。 – buddyp450

+0

理想的には、 "方法"について心配するべきではありません。あなたは状態に基づいて行動するべきです。おそらく、動的にロードされたコンポーネントが、それがどのようなコンポーネントであるかを報告するアクション(またはコールバックを呼び出す)を送り、それに基づいて親コンポーネントに決定を下させることができます。同様に、「兄弟姉妹」レベルの振る舞いは、通常https://facebook.github.io/react/docs/lifting-state-up.htmlに従って、親に「持ち上げられる」べきである。しかし、一般的には、「リアクションウェイ」は状態を基にUIを動かすことであり、コンポーネントインスタンスと直接対話することはありません。 – markerikson

関連する問題