Help us understand the problem. What is going on with this article?

React HooksでContainerってどうやって作るの?

ReactでReduxデータの操作をするとき、componentファイルに描画コードとデータ操作コードを書いても良いのですが、Reduxと描画のテストを別々にできない、という欠点もあるので、描画はComponentファイルに書いてReduxのデータ関連はContainerファイルに書く、ということをします。下記がContainerファイルの例です。

HogeContainer.ts
import { connect, ConnectedComponentClass } from 'react-redux'
import { Dispatch, AnyAction } from 'redux'

const mapStateToProps: (state: RooteState) => HogeContainerStateObj = (state: RooteState) => {
  return {
    hogeState: state.hogeState
  }
}

const mapDispatchToProps = ( dispatch: Dispatch<AnyAction> ) => {
  return {
    activateHogeApi: (): void => {
      dispatch(postHogeApi())
    }
  }
}

const HogeContainer = connect( mapStateToProps, mapDispatchToProps )(HogeComponent)

export default HogeContainer

これは何をやっているかといいますと、HogeComponent側で必要となるReduxのStateとActionをPropsとして、HogeComponentに渡しているのです。渡し方としては、mapStateToProps にStateを、 mapDispatchToProps にActionをそれぞれ持ち、それらを connect を使用して、HogeComponentに渡しています。HogeComponentでconsole.logでPropsを見ると、hogeStateactivateHogeApiが渡ってきていると思います。

ContainerはこのようにconnectしてComponentにReduxのデータを渡しています。これをHooksで書き換えると以下のようになります。

HogeContainer.tsx
import React, { useCallback } from 'react'
import { useSelector, useDispatch } from 'react-redux'

const mapStateToProps = () => {
  const hogeState = useSelector<RooteState, HogeState>(
    (state: RooteState) => state.hogeState
  )
  return { hogeState }
}

const mapDispatchToProps = () => {
  const dispatch = useDispatch()
  const activateHogeApi = useCallback((): void => {
    dispatch(postHogeApi())
  }, [dispatch])
  return { activateHogeApi }
}

const HogeContainer = (props): JSX.Element => {
  const _props = { ...mapStateToProps(), ...mapDispatchToProps(), ...props }
  return <HogeComponent {..._props} />
}

export default HogeContainer

やろうとしていることはHogeComponentにReduxの必要なデータを渡すということなのでそこは変わりませんが、書き方は少し違います。React Hooksには useState useReducer といったHooksAPIがあり、頭に use がつく特徴を持っています。

そして今回でいうと、 useSelectoruseDispatchuseCallback を使用しています。詳細はググってもらえるとわかるのですが、本当に簡単にいうと、useSelector はStateをみる、 useDispatch はdispatch使う、 useCallback はメソッド呼び出す、です。

結局、それぞれの変数にStateとActionをreturnしているだけです。そしてここで違ってくるのが、HogeContainerをJSX扱いする、ということです。どういうことかというと、 connect を使用していた部分を、普通にHogeComponentにデータを渡して、そのHogeComponentをHogeContainerというJSXで使用するだけ、です。

正直ここに書いてことを読むだけではHooksにわざわざ書き換える意味がないのでは?と思うかもしれません。しかし使用してみると、データの更新やファイルの扱いやすさ、というものが見えてくるので、新しく作るComponentにはReact Hooksを使用してみてください。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away