メインコンテンツへスキップ

connect()

ヒント

connect はReact-Redux 8.xでも動作し、サポートされています。ただし、フックAPIをデフォルトとして使用することをお勧めします

概要

connect() 関数は、ReactコンポーネントをReduxストアに接続します。

ストアから必要なデータの一部と、ストアにアクションをディスパッチするために使用できる関数を、接続されたコンポーネントに提供します。

渡されたコンポーネントクラスを変更するのではなく、渡されたコンポーネントをラップする新しい接続済みコンポーネントクラスを返します。

function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)

mapStateToPropsmapDispatchToProps は、それぞれReduxストアの statedispatch を処理します。statedispatch は、最初の引数としてmapStateToProps または mapDispatchToProps 関数に渡されます。

mapStateToPropsmapDispatchToProps の戻り値は、内部的にはそれぞれ statePropsdispatchProps と呼ばれます。これらは、定義されている場合は最初の引数と2番目の引数としてmergeProps に渡され、3番目の引数は ownProps となります。結合された結果(一般的に mergedProps と呼ばれます)は、接続されたコンポーネントに渡されます。

connect() パラメータ

connect は、すべてオプションの4つの異なるパラメータを受け入れます。慣例により、それらは次のように呼び出されます。

  1. mapStateToProps?: Function
  2. mapDispatchToProps?: Function | Object
  3. mergeProps?: Function
  4. options?: Object

mapStateToProps?: (state, ownProps?) => Object

mapStateToProps関数が指定されている場合、新しいラッパーコンポーネントはReduxストアの更新を購読します。つまり、ストアが更新されるたびに、mapStateToPropsが呼び出されます。mapStateToProps の戻り値はプレーンオブジェクトでなければならず、それはラップされたコンポーネントのプロパティにマージされます。ストアの更新を購読したくない場合は、mapStateToPropsの代わりにnullまたはundefinedを渡します。

パラメータ

  1. state: Object
  2. ownProps?: Object

mapStateToProps関数は、最大2つのパラメータを取ります。宣言された関数パラメータの数(別名アリティ)は、それがいつ呼び出されるかに影響します。これは、関数がownPropsを受け取るかどうかも決定します。詳細はこちらを参照してください。

state

mapStateToProps関数が1つのパラメータを取るように宣言されている場合、ストアの状態が変更されるたびに呼び出され、ストアの状態が唯一のパラメータとして渡されます。

const mapStateToProps = (state) => ({ todos: state.todos })
ownProps

mapStateToProps関数が2つのパラメータを取るように宣言されている場合、ストアの状態が変更された時、またはラッパーコンポーネントが新しいプロパティを受け取った時(浅い等価比較に基づく)に呼び出されます。ストアの状態が最初の引数として、ラッパーコンポーネントのプロパティが2番目の引数として渡されます。

2番目のパラメータは、通常、慣例によりownPropsと呼ばれます。

const mapStateToProps = (state, ownProps) => ({
todo: state.todos[ownProps.id],
})

戻り値

mapStateToProps関数はオブジェクトを返すことが期待されています。このオブジェクトは、通常statePropsと呼ばれ、接続されたコンポーネントのプロパティとしてマージされます。mergePropsを定義する場合、それはmergePropsの最初のパラメータとして渡されます。

mapStateToPropsの戻り値は、接続されたコンポーネントが再レンダリングされるかどうかを決定します(詳細はこちら)。

mapStateToPropsの推奨される使用方法の詳細については、mapStateToPropsの使い方に関するガイドを参照してください。

mapStateToPropsmapDispatchToPropsをファクトリ関数として定義できます。つまり、オブジェクトではなく関数を返します。この場合、返された関数は実際のmapStateToPropsまたはmapDispatchToPropsとして扱われ、後続の呼び出しで呼び出されます。ファクトリ関数に関するメモ、またはパフォーマンス最適化に関するガイドを参照してください。

mapDispatchToProps?: Object | (dispatch, ownProps?) => Object

慣例的にmapDispatchToPropsと呼ばれ、connect()の2番目のパラメータは、オブジェクト、関数、または何も供給されない場合があります。

connect()に2番目のパラメータを供給しない場合、コンポーネントはデフォルトでdispatchを受け取ります。

// do not pass `mapDispatchToProps`
connect()(MyComponent)
connect(mapState)(MyComponent)
connect(mapState, null, mergeProps, options)(MyComponent)

mapDispatchToPropsを関数として定義する場合、最大2つのパラメータで呼び出されます。

パラメータ

  1. dispatch: Function
  2. ownProps?: Object
dispatch

mapDispatchToPropsが1つのパラメータを取る関数として宣言されている場合、ストアのdispatchが渡されます。

const mapDispatchToProps = (dispatch) => {
return {
// dispatching plain actions
increment: () => dispatch({ type: 'INCREMENT' }),
decrement: () => dispatch({ type: 'DECREMENT' }),
reset: () => dispatch({ type: 'RESET' }),
}
}
ownProps

mapDispatchToProps関数が2つのパラメータを取るように宣言されている場合、dispatchが最初のパラメータとして、ラッパーコンポーネントに渡されたプロパティが2番目のパラメータとして渡され、接続されたコンポーネントが新しいプロパティを受け取るたびに再呼び出されます。

2番目のパラメータは、通常、慣例によりownPropsと呼ばれます。

// binds on component re-rendering
<button onClick={() => this.props.toggleTodo(this.props.todoId)} />

// binds on `props` change
const mapDispatchToProps = (dispatch, ownProps) => ({
toggleTodo: () => dispatch(toggleTodo(ownProps.todoId)),
})

mapDispatchToPropsの宣言された関数パラメータの数によって、ownPropsを受け取るかどうかが決まります。詳細はこちらを参照してください。

戻り値

mapDispatchToProps関数はオブジェクトを返すことが期待されています。オブジェクトの各フィールドは関数であり、それを呼び出すことでストアにアクションがディスパッチされることが期待されます。

mapDispatchToProps関数の戻り値はdispatchPropsとみなされます。それは接続されたコンポーネントのプロパティとしてマージされます。mergePropsを定義する場合、それはmergePropsの2番目のパラメータとして渡されます。

const createMyAction = () => ({ type: 'MY_ACTION' })
const mapDispatchToProps = (dispatch, ownProps) => {
const boundActions = bindActionCreators({ createMyAction }, dispatch)
return {
dispatchPlainObject: () => dispatch({ type: 'MY_ACTION' }),
dispatchActionCreatedByActionCreator: () => dispatch(createMyAction()),
...boundActions,
// you may return dispatch here
dispatch,
}
}

推奨される使用方法の詳細については、mapDispatchToPropsの使い方に関するガイドを参照してください。

mapStateToPropsmapDispatchToPropsをファクトリ関数として定義できます。つまり、オブジェクトではなく関数を返します。この場合、返された関数は実際のmapStateToPropsまたはmapDispatchToPropsとして扱われ、後続の呼び出しで呼び出されます。ファクトリ関数に関するメモ、またはパフォーマンス最適化に関するガイドを参照してください。

オブジェクト簡略記法

mapDispatchToPropsは、各フィールドがアクションクリエイターであるオブジェクトにすることができます。

import { addTodo, deleteTodo, toggleTodo } from './actionCreators'

const mapDispatchToProps = {
addTodo,
deleteTodo,
toggleTodo,
}

export default connect(null, mapDispatchToProps)(TodoApp)

この場合、React-ReduxはbindActionCreatorsを使用して、ストアのdispatchを各アクションクリエイターにバインドします。結果はdispatchPropsとみなされ、接続されたコンポーネントに直接マージされるか、または2番目の引数としてmergePropsに渡されます。

// internally, React-Redux calls bindActionCreators
// to bind the action creators to the dispatch of your store
bindActionCreators(mapDispatchToProps, dispatch)

オブジェクト簡略記法の使用方法については、mapDispatchToPropsガイドのこちらのセクションもご覧ください。

mergeProps?: (stateProps, dispatchProps, ownProps) => Object

指定されている場合、ラップされたコンポーネントの最終的なプロパティの決定方法を定義します。mergePropsを提供しない場合、ラップされたコンポーネントはデフォルトで{ ...ownProps, ...stateProps, ...dispatchProps }を受け取ります。

パラメータ

mergePropsは最大3つのパラメータで指定する必要があります。それらはそれぞれ、mapStateToProps()mapDispatchToProps()、およびラッパーコンポーネントのpropsの結果です。

  1. stateProps
  2. dispatchProps
  3. ownProps

そこから返すプレーンオブジェクトのフィールドは、ラップされたコンポーネントのプロパティとして使用されます。この関数を指定して、プロパティに基づいて状態のスライスを選択したり、アクションクリエイターをプロパティの特定の変数にバインドしたりできます。

戻り値

mergePropsの戻り値はmergedPropsと呼ばれ、そのフィールドはラップされたコンポーネントのプロパティとして使用されます。

注:mergePropsで新しい値を作成すると、再レンダリングが発生します。不要な再レンダリングを避けるために、フィールドをメモ化することをお勧めします。

options?: Object

{
context?: Object,
areStatesEqual?: Function,
areOwnPropsEqual?: Function,
areStatePropsEqual?: Function,
areMergedPropsEqual?: Function,
forwardRef?: boolean,
}

context: Object

注記: このパラメータはv6.0以降でサポートされています。

React-Redux v6では、React-Reduxで使用されるカスタムコンテキストインスタンスを指定できます。 カスタムコンテキストのインスタンスを<Provider />と接続されたコンポーネントの両方に渡す必要があります。接続されたコンポーネントへのコンテキストの渡し方は、オプションのフィールドとしてここで渡すか、レンダリング時にプロップとして接続されたコンポーネントに渡すかの2通りがあります。

// const MyContext = React.createContext();
connect(mapStateToProps, mapDispatchToProps, null, { context: MyContext })(
MyComponent,
)

areStatesEqual: (next: Object, prev: Object, nextOwnProps: Object, prevOwnProps: Object) => boolean

  • デフォルト値: strictEqual: (next, prev) => prev === next

受信したストアの状態を以前の値と比較します。

const areStatesEqual = (next, prev) =>
prev.entities.todos === next.entities.todos

mapStateToProps関数が計算コストが高く、状態のごく一部しか考慮していない場合、areStatesEqualをオーバーライドすることを検討してください。 上記の例では、状態の一部の変更以外は無視されます。さらに、areStatesEqualnextOwnPropsprevOwnPropsを提供するため、必要に応じて、接続されたコンポーネントが関心を持つ状態のスコープをより効果的に設定できます。

これは、mapStateToProps関数に応じて、他の等価性チェックにも影響を与える可能性があります。

areOwnPropsEqual: (next: Object, prev: Object) => boolean

  • デフォルト値: shallowEqual: (objA, objB) => boolean(オブジェクトの各フィールドが等しい場合にtrueを返します)

受信したプロップを以前の値と比較します。

受信プロップをホワイトリスト登録する方法として、areOwnPropsEqualをオーバーライドすることを検討してください。 その場合、mapStateToPropsmapDispatchToPropsmergePropsも実装してプロップをホワイトリスト登録する必要があります。(例えば、recomposeのmapPropsを使用するなど、他の方法で実現する方が簡単かもしれません。)

areStatePropsEqual: (next: Object, prev: Object) => boolean

  • 型: function
  • デフォルト値: shallowEqual

mapStateToPropsの結果を以前の値と比較します。

areMergedPropsEqual: (next: Object, prev: Object) => boolean

  • デフォルト値: shallowEqual

mergePropsの結果を以前の値と比較します。

mapStateToPropsが、関連プロップが変更された場合にのみ新しいオブジェクトを返すメモ化されたセレクタを使用している場合、areStatePropsEqualをオーバーライドしてstrictEqualを使用することを検討してください。これにより、mapStateToPropsが呼び出されるたびに個々のプロップで追加の等価性チェックを回避できるため、わずかなパフォーマンス向上になります。

セレクタが複雑なプロップ(例:ネストされたオブジェクト、新しい配列など)を生成する場合、areMergedPropsEqualをオーバーライドしてdeepEqualを実装することを検討してください。(ディープイコールチェックは、再レンダリングするよりも高速な場合があります。)

forwardRef: boolean

注記: このパラメータはv6.0以降でサポートされています。

{forwardRef: true}connectに渡された場合、接続されたラッパーコンポーネントへの参照を追加すると、実際にはラップされたコンポーネントのインスタンスが返されます。

connect()の戻り値

connect()の戻り値は、コンポーネントを受け取り、注入する追加のプロップを含むラッパーコンポーネントを返すラッパー関数です。

import { login, logout } from './actionCreators'

const mapState = (state) => state.user
const mapDispatch = { login, logout }

// first call: returns a hoc that you can use to wrap any component
const connectUser = connect(mapState, mapDispatch)

// second call: returns the wrapper component with mergedProps
// you may use the hoc to enable different components to get the same behavior
const ConnectedUserLogin = connectUser(Login)
const ConnectedUserProfile = connectUser(Profile)

ほとんどの場合、ラッパー関数は一時変数に保存されることなく、すぐに呼び出されます。

import { login, logout } from './actionCreators'

const mapState = (state) => state.user
const mapDispatch = { login, logout }

// call connect to generate the wrapper function, and immediately call
// the wrapper function to generate the final wrapper component.

export default connect(mapState, mapDispatch)(Login)

使用例

connectは非常に柔軟であるため、その呼び出し方法の追加例を参照すると役立つ場合があります。

  • dispatchのみを注入し、ストアを監視しません。
export default connect()(TodoApp)
  • ストアを購読せずに、すべてのaction creator(addTodocompleteTodoなど)を注入します。
import * as actionCreators from './actionCreators'

export default connect(null, actionCreators)(TodoApp)
  • dispatchとグローバル状態のすべてのフィールドを注入します。

これは行わないでください! TodoAppは状態の変更のたびに再レンダリングされるため、パフォーマンスの最適化がすべて無効になります。ビュー階層内の複数のコンポーネントに、関連する状態のスライスのみを監視するより粒度の細かいconnect()を使用する方が優れています。

// don't do this!
export default connect((state) => state)(TodoApp)
  • dispatchtodosを注入します。
function mapStateToProps(state) {
return { todos: state.todos }
}

export default connect(mapStateToProps)(TodoApp)
  • todosとすべてのaction creatorを注入します。
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
return { todos: state.todos }
}

export default connect(mapStateToProps, actionCreators)(TodoApp)
  • todosとすべてのaction creator(addTodocompleteTodoなど)をactionsとして注入します。
import * as actionCreators from './actionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
return { actions: bindActionCreators(actionCreators, dispatch) }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • todosと特定のaction creator(addTodo)を注入します。
import { addTodo } from './actionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
return bindActionCreators({ addTodo }, dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • todosと特定のaction creator(addTododeleteTodo)を省略記法で注入します。
import { addTodo, deleteTodo } from './actionCreators'

function mapStateToProps(state) {
return { todos: state.todos }
}

const mapDispatchToProps = {
addTodo,
deleteTodo,
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • todostodoActionCreatorstodoActionsとして、counterActionCreatorscounterActionsとして注入します。
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
return {
todoActions: bindActionCreators(todoActionCreators, dispatch),
counterActions: bindActionCreators(counterActionCreators, dispatch),
}
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • todostodoActionCreatorscounterActionCreatorsをまとめてactionsとして注入します。
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(
{ ...todoActionCreators, ...counterActionCreators },
dispatch,
),
}
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • todos、すべてのtodoActionCreatorscounterActionCreatorsをプロップとして直接注入します。
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
return bindActionCreators(
{ ...todoActionCreators, ...counterActionCreators },
dispatch,
)
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • プロップに応じて特定のユーザーのtodosを注入します。
import * as actionCreators from './actionCreators'

function mapStateToProps(state, ownProps) {
return { todos: state.todos[ownProps.userId] }
}

export default connect(mapStateToProps)(TodoApp)
  • プロップに応じて特定のユーザーのtodosを注入し、アクションにprops.userIdを注入します。
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
return { todos: state.todos }
}

function mergeProps(stateProps, dispatchProps, ownProps) {
return Object.assign({}, ownProps, {
todos: stateProps.todos[ownProps.userId],
addTodo: (text) => dispatchProps.addTodo(ownProps.userId, text),
})
}

export default connect(mapStateToProps, actionCreators, mergeProps)(TodoApp)

注記

mapToProps関数の引数の数

mapStateToPropsmapDispatchToPropsの宣言された関数パラメータの数は、それらがownPropsを受け取るかどうかを決定します。

注記: 関数の正式な定義に必須パラメータが1つだけ含まれている場合(関数のlengthが1の場合)、ownPropsmapStateToPropsmapDispatchToPropsに渡されません。 例えば、以下のように定義された関数は、第2引数としてownPropsを受け取りません。ownPropsの入力値がundefinedの場合、デフォルトの引数値が使用されます。

function mapStateToProps(state) {
console.log(state) // state
console.log(arguments[1]) // undefined
}

const mapStateToProps = (state, ownProps = {}) => {
console.log(state) // state
console.log(ownProps) // {}
}

必須パラメータがないか、2つのパラメータを持つ関数*ownPropsを受け取ります。

const mapStateToProps = (state, ownProps) => {
console.log(state) // state
console.log(ownProps) // ownProps
}

function mapStateToProps() {
console.log(arguments[0]) // state
console.log(arguments[1]) // ownProps
}

const mapStateToProps = (...args) => {
console.log(args[0]) // state
console.log(args[1]) // ownProps
}

ファクトリ関数

mapStateToPropsまたはmapDispatchToProps関数が関数を返す場合、コンポーネントのインスタンス化時に1回呼び出され、その戻り値が、後続の呼び出しでの実際のmapStateToPropsmapDispatchToProps関数としてそれぞれ使用されます。

ファクトリ関数は、通常、メモ化されたセレクタで使用されます。これにより、クロージャ内でコンポーネントインスタンス固有のセレクタを作成できます。

const makeUniqueSelectorInstance = () =>
createSelector([selectItems, selectItemId], (items, itemId) => items[itemId])
const makeMapState = (state) => {
const selectItemForThisComponent = makeUniqueSelectorInstance()
return function realMapState(state, ownProps) {
const item = selectItemForThisComponent(state, ownProps.itemId)
return { item }
}
}
export default connect(makeMapState)(SomeComponent)

レガシーバージョンのドキュメント

connect APIは、すべての主要バージョン間でほぼ完全にAPI互換性を維持してきましたが、バージョンごとにオプションと動作に小さな変更がありました。

レガシーバージョン5.xと6.xの詳細については、React Reduxリポジトリにあるこれらのアーカイブファイルを参照してください。