2016-05-10 11 views
3

私はcontainer componentsをReactとReduxで実装しようとしていますが、ライフサイクルの方法については何をすべきか分かりません。コンテナまたはプレゼンテーションコンポーネント。ライフサイクルメソッドはDOMアップデートを制御するためにプレゼンテーションであると主張することができますが、その点でも動作的ではありませんか?ライフサイクルメソッドをコンテナコンポーネントまたはプレゼンテーションコンポーネントに実装する必要がありますか?

また、これまでに見たコンテナコンポーネントの実装では、自分自身と同様にreact-reduxバインディングを使用しています。懸念を明確に分離しても、行動コンポーネントの場合はReact.Componentから継承するのが適切ですか?例えば

、私が働いてどのアプリがshouldComponentUpdate方法で、Tabプレゼンテーションコンポーネントがありますときに、コンポーネントがすべきことは、コントロールとして一方

class Tabs extends Component { 
    shouldComponentUpdate(nextProps) { 
     const { activeTab } = this.props; 
     return activeTab !== nextProps.activeTab; 
    } 

    [...] 
} 

、これはプレゼンテーションの懸念のように思えます再レンダリングする。しかし、これは、ユーザーが新しいタブをクリックしてアクションを介してアプリケーションの状態を更新するときの処理方法です。したがって、これを動作として分類します。

+0

私はそれがライフサイクルの方法を使用しているかどうかにかかっていると思います。あなたは例を挙げることができますか? – Aaron

+0

確かに、私は私の質問を更新しました。 –

答えて

4

データは、できるだけツリーのルートの近くで制御する必要があります。これを行うと、単純な最適化が提供され、必要なものだけを渡すことになります。

これは、ライフサイクルコンポーネントを制御する場所にバブルします。 mgmcdermottが述べたように、多くのライフサイクルコンポーネントは実際にあなたがやっていることに依存しますが、最も簡単なシナリオは、最も単純で愚かなコンポーネントを持つことです。

ほとんどの私のプロジェクトでは、私の反応ディレクトリには、components/views/があります。私の好みでは、ビューはできるだけ多くの不平を言っていなければなりません。つまり、componentDidMount,componentWillMountcomponentWillUnmountなどのライフサイクルメソッドを使用して構築したコンポーネントがいくつかありますが、私の見解では、自分の仕事の1つがデータフローを制御しているため、 。つまり、componentShouldUpdateがそこに住むことになります。個人的には、componentShouldUpdateは純粋に最終行の最適化だと思います。再レンダリング中に大きなパフォーマンスの問題が発生している場合にのみ使用します。

私はあなたが「React.Componentから継承しました」という質問をよく理解していません。純粋な関数es6 class、またはReact.createClassを使用するかどうかを尋ねる場合は、標準規則があるかどうかはわかりませんが、一貫性があるのは良いことです。

ビヘイビアまたはプレゼンテーションを処理するかどうかを指定するには、ビヘイビアはクリックですが、再描画はプレゼンテーションです。あなたの行動は、Tabコンポーネントに存在する可能性があります。ここでは、Tabsビューに再描画します。 Tabsビューはあなたのメソッドをreduxから渡して、現在アクティブなタブを個々のTabコンポーネントに設定し、タブ切り替えの動作をreduxに送信して、componentShouldUpdateのプレゼンテーションを行うことができます。それは理にかなっていますか?

コンテナ内のmapToDispatchメソッドにはアクティブなタブを設定する関数があります。activateTab(idx)という名前のタブをインデックスとします。コンテナは、コントロールする包含コンポーネント(views/Tabs)にコンテナを渡し、そのメソッドをcomponents/Tabに渡します。 components/TabonClickメソッドを持ちます。これはDOM要素の1つをリッスンし、this.props.activateTab(myIndex)を呼び出します(components/TabにバインドされたバージョンのactivateTabを渡すことができるため、独自のインデックスを認識する必要はありません)あなたのデータをviews/Tabsに返します。views/Tabsは、reduxからのデータに基づいてcomponentShouldUpdateを処理できます。

拡張編集:これは受け入れられたとマークされているので、コードサンプルを平均的な人に利用できるものに吹き飛ばします。

これは非常にアプリに依存する可能性があるので、私はずっと還元を書くつもりはありませんが、あなたはactiveTabIdxと親がぶら下がっていると仮定しています。

コンテナ/ TabExample.jsx

import { connect } from 'react-redux' 
import Tabs from 'views/Tabs.js' 

const mapStateToProps = function (state) { 
    return { 
    activeTabIdx: state.activeTabIdx 
    // And whatever else you have... 
    } 
} 

const mapDispatchToProps = function (dispatch) { 
    return { 
    activateTab: function (idx) { 
     dispatch({ 
     action: 'ACTIVATE_TAB_IDX', 
     idx: idx 
     }) // You probably want this in a separate actions/tabs.js file... 
    } 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(Tabs) 

ビュー/ Tabs.js

import React, { createClass } from 'react' 
import Tab from 'components/Tab.js' 

const { number, func } = React.PropTypes 

// Alternatively, you can use es6 classes... 
export default createClass({ 
    propTypes: { 
    activeTabIdx: number.isRequired, 
    activateTab: func.isRequired 
    }, 

    render() { 
    const { activeTabIdx } = this.props 
    const tabs = ['Tab 1', 'Tab 2', 'Tab 3'] 

    return (
     <div className='view__tabs'> 
     <ol className='tabs'> 
      {this.renderTabLinks(tabs, activeTabIdx)} 
     </ol> 
     </div> 
    ) 
    }, 

    renderTabLinks (tabs, activeTabIdx) { 
    return tabs.map((tab, idx) => { 
     return (
     <Tab 
      onClick={this.props.activateTabIdx.bind(this, idx)} 
      isActive={idx === activeTabIdx} 
     > 
      {tab} 
     </Tab> 
    ) 
    }) 
    } 
}) 

コンポーネント/ Tab.js

import React, { createClass } from 'react' 

const { func, bool } = React.PropTypes 

// Alternatively, you can use es6 classes... 
export default createClass({ 
    propTypes: { 
    children: node.isRequired, 
    onClick: func.isRequired, 
    isActive: bool.isRequired 
    }, 

    handleClick (e) { 
    const { isActive, onClick } = this.props 

    e.preventDefault() 

    if (!isActive) { 
     onClick() 
    } 
    }, 

    render() { 
    const { children, isActive } = this.props 

    const tabClass = isActive 
     ? 'tabs__items tabs__items--active' 
     : 'tabs__items' 

    return (
     <li className={tabClass}> 
     <a className='tabs__item-link' onClick={this.handleClick}> 
      {children} 
     </a> 
     </li> 
    ) 
    } 

それは大部分が正しいことをするでしょう。これはタブの内容を扱う/気にしないことに注意してください。その結果、ビューを別の方法で構造化することができます。

+0

Re Tabの例、私はそれが理にかなっていると思う!ありがとう! :) –

+0

私の喜び。私の、またはmgmcdermottの回答を受け入れたものとしてマークすることを忘れないでください。私はあなたの質問に答える限り、私の答えは本当に彼の吹き飛ばされたバージョンです。 – OzBarry

+0

私の展開した例では、ページに多数の**ビュー/タブ**インスタンスがある場合、2つのオプションがあります。アクティブなタブがあまり気にしない場合は、ローカル状態を使用することができます。あなたはこれを行うreduxからいくつかの利点を失う。あるいは、各タブセットに対して一連のactiveTabIdxインスタンスを記述するより頑強なredux状態を持つことができます。 – OzBarry

4

これは意見の問題だと思います。私は個人的に私のプレゼンテーションの構成要素をできるだけ愚かなものにしておきたい。これにより、私の発表するコンポーネントの大部分をstateless functionsと書くことができます。これは、Reactアップデートでますます最適化されています。これは、私がそれを手助けすることができれば、プレゼンテーションコンポーネントの内部状態を防ぐことを意味します。

あなたの例の場合、componentShouldUpdateはこのコンポーネントが使用されるたびに渡されるべきであるので、現実的な問題ではないと私は信じています。このコンポーネントはアプリケーションの状態を更新しますが、内部状態がないため、必ずしも動作するとは限りません。

もう一度、実際にはここでやり方が正しいか間違っているとは思わない。それはwhether or not Redux should handle all application stateについての議論を私に思い出させる。私は、プレゼンテーションコンポーネントをできるだけダン(再利用可能)なものにするというアイデアを考え続けるなら、どのような場合でもライフサイクルメソッドを配置する正しい場所を理解することができます。

1

あなたの質問はあまり正確ではありません。ライフサイクル・メソッドを使用しての

単純な行為は、プレゼンテーション又は容器コンポーネントとしてのコンポーネントを定義していません。

ライフサイクルメソッドはまさにそれです。あなたが好きなことを何でもできるように、あなたの便宜のためのフックです。

コンテナコンポーネント通常は、それらのライフサイクルメソッドでは、アプリケーションのデータフローに自分自身を接続するいくつかのセットアップを行います。これがコンテナコンポーネントになるのではなく、ライフサイクルメソッドを使用しているという事実ではありません。

表現的要素は通常ダムとステートレスあり、したがって、彼らは通常にフックそれらのライフサイクルメソッドは必要ありません。これが常にそうであるということではありません。プレゼンテーションコンポーネントはステートフルであることがあります(これはしばしば望ましくありません)。ステートレスコンポーネントはライフサイクルメソッドを使用できますが、コンテナコンポーネントとはまったく異なる方法で使用できます。ドキュメントにイベントリスナーを追加したり、完全にステートレスな方法で入力のカーソル位置を調整したりすることがあります。

そして、おそらくあなたは、コンテナコンポーネントとステートフルコンポーネントを混合しています。これらは異なるものであり、コンテナコンポーネントはステートフルですが、ステートフルコンポーネントは必ずしもコンテナコンポーネントとして機能するとは限りません。

+0

私はそれを高水準の記述を与えたコンテナコンポーネントにしていますが、おそらくステートフルとコンテナコンポーネントの間にいくつかの_overlap_があると思います。おそらく –

+0

。 「コンテナ」コンポーネントは、MVCパターンで「コントローラ」と同様のことを行うと考えると便利です。まったく同じ動作ではありませんが、かなり近いです。一方、「ステートフル」コンポーネントは、単にある状態を保持するコンポーネントです。 – timetowonder

関連する問題