データは、できるだけツリーのルートの近くで制御する必要があります。これを行うと、単純な最適化が提供され、必要なものだけを渡すことになります。
これは、ライフサイクルコンポーネントを制御する場所にバブルします。 mgmcdermottが述べたように、多くのライフサイクルコンポーネントは実際にあなたがやっていることに依存しますが、最も簡単なシナリオは、最も単純で愚かなコンポーネントを持つことです。
ほとんどの私のプロジェクトでは、私の反応ディレクトリには、components/
とviews/
があります。私の好みでは、ビューはできるだけ多くの不平を言っていなければなりません。つまり、componentDidMount
,componentWillMount
、componentWillUnmount
などのライフサイクルメソッドを使用して構築したコンポーネントがいくつかありますが、私の見解では、自分の仕事の1つがデータフローを制御しているため、 。つまり、componentShouldUpdate
がそこに住むことになります。個人的には、componentShouldUpdate
は純粋に最終行の最適化だと思います。再レンダリング中に大きなパフォーマンスの問題が発生している場合にのみ使用します。
私はあなたが「React.Component
から継承しました」という質問をよく理解していません。純粋な関数es6 class
、またはReact.createClass
を使用するかどうかを尋ねる場合は、標準規則があるかどうかはわかりませんが、一貫性があるのは良いことです。
ビヘイビアまたはプレゼンテーションを処理するかどうかを指定するには、ビヘイビアはクリックですが、再描画はプレゼンテーションです。あなたの行動は、Tab
コンポーネントに存在する可能性があります。ここでは、Tabs
ビューに再描画します。 Tabs
ビューはあなたのメソッドをreduxから渡して、現在アクティブなタブを個々のTab
コンポーネントに設定し、タブ切り替えの動作をreduxに送信して、componentShouldUpdate
のプレゼンテーションを行うことができます。それは理にかなっていますか?
コンテナ内のmapToDispatch
メソッドにはアクティブなタブを設定する関数があります。activateTab(idx)
という名前のタブをインデックスとします。コンテナは、コントロールする包含コンポーネント(views/Tabs
)にコンテナを渡し、そのメソッドをcomponents/Tab
に渡します。 components/Tab
はonClick
メソッドを持ちます。これは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>
)
}
それは大部分が正しいことをするでしょう。これはタブの内容を扱う/気にしないことに注意してください。その結果、ビューを別の方法で構造化することができます。
私はそれがライフサイクルの方法を使用しているかどうかにかかっていると思います。あなたは例を挙げることができますか? – Aaron
確かに、私は私の質問を更新しました。 –