質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

452閲覧

[Redux] dispatchを分割代入して子コンポーネントに渡せる理由がわかりません。

tomoharu

総合スコア107

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2019/06/21 16:38

編集2019/06/22 00:17

当方Redux 初心者です。
勉強していた中に、以下のようなコードが出てきました。

import React from 'react'; import { connect } from 'react-redux'; import { removeExpense } from '../actions/expenses'; const ExpenseListItem = ({ dispatch, id, description, amount, createdAt }) => ( <div> <h1>{description}</h1> <p>{amount}-{createdAt}</p> <button onClick={() => { dispatch(removeExpense({id})) }}> remove </button> </div> ) export default connect()(ExpenseListItem);

上記はコンポーネントなのですが、これの親となるコンポーネントが以下です。

import ExpenseListItem from './ExpenseListItem' const ExpenseList = (props) => ( <div> <h1> Expense List</h1> {props.expenses.map((expense) => { return <ExpenseListItem key={expense.id}{...expense}/> })} </div> );

となります。子コンポーネントに対して、expenseというハッシュを渡していて、
その中身の例としては、

amount: 1000 createdAt: 3000 description: "water bill" id: "45853915-33c9-4e28-8d8a-3247083300a0"

このような形になります。

質問1:
ハッシュであるexpenseを分割代入して子供に渡しているのはわかるのですが、dispatchというメソッドはそのハッシュの中にはないはずなのに、なぜ分割代入の要領で、親から子に渡すことができるのでしょうか。

質問2:
この分割代入の要領で子供に渡すことができるのはdispatchのみですか?他のメソッドも渡すことができるのでしょうか

何卒宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun68ykt

2019/06/21 23:54 編集

こんにちは。質問に挙げられているコードに以下の2点を追記して頂きたいです。(1) ExpenseListItem を export している行 (2) ExpenseList で ExpenseListItem を import している行
tomoharu

2019/06/22 00:18

ご質問ありがとうございます。対応しました。
jun68ykt

2019/06/22 02:40

追記ありがとうございます。回答しました。
guest

回答2

0

ベストアンサー

こんにちは。

質問1:

ハッシュであるexpenseを分割代入して子供に渡しているのはわかるのですが、dispatchというメソッドはそのハッシュの中にはないはずなのに、なぜ分割代入の要領で、親から子に渡すことができるのでしょうか。

ExpenseListItem に props経由で dispatch が渡されてくる理由は、

javascript

1export default connect()(ExpenseListItem);

としているからです。
この connect の書き方は、react-redux の公式ドキュメントにある connect() の使い方の事例の一番上の例

・Inject just dispatch and don't listen to store

javascript

1export default connect()(TodoApp)

と同じように、mapStateToProps, mapDispatchToProps を与えない使い方です。この場合、redux からprops経由で渡されるものは、(ドキュメントに Inject just dispatch とあるとおり、) dispatchだけです。

connectによる効果によって dispatchが props に渡されることは、以下のようにすれば確かめられます。

javascript

1export default connect()(ExpenseListItem);

を、以下のように単にExpenseListItem をそのまま export するように書き換えます。

javascript

1export default ExpenseListItem;

上記のようにしてから、ExpenseList を画面に表示させ、各ExpenseListItemの [remove]ボタンをクリックしてみると、アクションが発行されることはなく、おそらく dispatch is not a function というエラーメッセージがコンソールに表示されると思います。

質問2:

この分割代入の要領で子供に渡すことができるのはdispatchのみですか?他のメソッドも渡すことができるのでしょうか

渡せます。
以下、その一例です。

javascript

1export default connect()(ExpenseListItem);

としているところを

javascript

1const mapDispatchToProps = dispatch => ({ 2 remove: id => { dispatch(removeExpense({id})); } 3}); 4 5export default connect(null, mapDispatchToProps)(ExpenseListItem);

とすると、上記の remove が props 経由で渡されるので、ExpenseListItem は以下のようになります。

jsx

1import React from 'react'; 2import { connect } from 'react-redux'; 3import { removeExpense } from '../actions/expenses'; 4 5const ExpenseListItem = ({ remove, id, description, amount, createdAt }) => ( 6 <div> 7 <h1>{description}</h1> 8 <p>{amount}-{createdAt}</p> 9 <button onClick={() => { 10 remove(id) 11 }}> 12 remove 13 </button> 14 </div> 15) 16

次に、 connect の働きを把握するために HOC という用語を説明します。

javascript

1export default connect()(ExpenseListItem);

connect() は関数を返します。どのような関数かというと、コンポーネントを受け取ってコンポーネントを返すような関数です。そのような関数のことを一般には Higher-Order Components (HOC)といいます。connect() はHOCを返しますが、どのようなことを提供してくれるHOCかといえば、引数で指定されたコンポーネント(上記では ExpenseListItem )に 「props 経由で dispatch が渡されてくる」という機能を追加したコンポーネントを返します。これを踏まえたうえで、

dispatchのみですか?

への回答として、上記のように、あるコンポーネントを、特別な用途に作られたHOCに渡して、機能拡張されたコンポーネントを得るという、別の例を挙げます。

画面のURLとコンポーネントをマッピングするためによく使用される react-router で提供される withRouter がそのようなHOCの例です。

withRouterの働きは、Aというコンポーネントがあったときに、withRouter(A) が返すコンポーネントを適切にルーティング設定すると、Aには、match, location, history の3点がprops経由で渡されますので、これらを使ってURLや画面遷移の操作等を実現できます。(ただしこれら3つのpropsは関数ではありません。connect()が返すHOC以外にも、Reactによる開発でよく使う HOCの事例として withRouter を挙げました。)

また、 HOCは自作することもできます。任意の名前、例えば何らかの x というprops を挿入するようなwithX という HOCを作っておいて、あるコンポーネント A でこの withX からの this.props.x を使いたいのであれば、Aのソースコードでexport するところを

javascript

1export default withX(A);

とすればよいです。
このようにすると、 A を使う側で、例えば <A /> のように何もpropsを渡さないとしても、Aの中では withX が渡してくれる想定のthis.props.x を何らかの用途に使うことができます。 props x を提供することで、何を A に機能追加したいのかは、withX で詳細を実装します。

以上、参考になれば幸いです。

追記

もし仮にmapStateToPropsを”与える”やり方で書いた場合においても、dispatchはpropsに渡されますか?

渡されます。

仮に redux state に、システムからのお知らせとして、 messages というプロパティがあるとします。これを ExpenseListItem で使いたいとき、 mapStateToProps

javascript

1const mapStateToProps = state => ({ 2 messages: state.messages 3});

としておいて、connect を

javascript

1export default connect(mapStateToProps)(ExpenseListItem);

と、mapStateToProps は指定するけれども mapDispatchToProps は指定しない書き方をすると、connect によってprops に渡されるのは messagesdispatch の2点ということになります。

投稿2019/06/22 02:39

編集2019/06/22 05:56
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tomoharu

2019/06/22 03:25

大変詳しいご回答ありがとうございます。質問1に関して1つだけ質問です。もし仮にmapStateToPropsを”与える”やり方で書いた場合においても、dispatchはpropsに渡されますか? 渡され方が異なるのでしょうか?
jun68ykt

2019/06/22 03:41

コメントありがとうございます。回答のほうに追記しました。
tomoharu

2019/06/23 02:41

ありがとうございます! まだ完全に腹に落ちている感じではないですが、とてもわかりやすい説明ありがとうございました。 勉強します。
jun68ykt

2019/06/23 03:03

どういたしまして。少しでもお役にたてたようでよかったです。
guest

0

ハッシュであるexpenseを分割代入して子供に渡しているのはわかるのですが、dispatchというメソッドはそのハッシュの中にはないはずなのに、なぜ分割代入の要領で、親から子に渡すことができるのでしょうか。

親から子に渡っているわけではありません。Reduxのconnect()が生成しています。

投稿2019/06/22 01:32

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tomoharu

2019/06/22 02:26

ご回答ありがとうございます。承知しました。 ただ、他のidやdescriptionと同様にあの引数の中に書けてしまうのが、どうにも混乱してしまいます。これはdispatchに限った話なのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問