Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@yutaro50

模写で"なんとなく"理解する React-Redux超基礎

More than 1 year has passed since last update.

理論そっちのけで、とりあえず簡単なアプリを作ってみます。

今回作るもの

なんてことのない、ただのカウントアプリです↓

giphy.gif

注意点

ただ模写していく事で「あ、なんとなく書けるかも」と思えることが目的です。
理論などの説明は下記リンク群が大変参考になりました。

全くつかめていない方は、これらを見てから書いてみるとわかりやすいと思います。

開発環境

カテゴリ バージョン   
OS macOS Mojave 10.14.4
Node.js 10.15.3
Yarn 1.13.0
React 16.8.6
Redux 4.0.1

模写の準備

開発環境の構築

Node.js, Yarnのインストール

ここの説明は省略します。
わからない人は、このQiitaが懇切丁寧です。

create-react-appのインストール

Facebook社が作ってくださった「create-react-app」という雛形をダウンロードします。

$ yarn global add create-react-app

※"./path/to/applciation"の部分で作成するアプリケーションへのパスを指定
$ create-react-app ./path/to/application

このような、React自身やその他諸々のライブラリをまとめて、雛形を作成してくれるツールを「boilerplate」と言います。

色々な種類がありますので、気になる方はこちらを参考に。

実際に雛形が作成され、下記のようなフォルダ・ファイル群が生成されます↓

.
├── README.md
├── node_modules
├── package.json
├── public
├── src
└── yarn.lock

とりあえず起動してみましょう。Reactのロゴがブラウザで表示されれば成功です。

$ yarn start

Redux, react-reduxのインストール

ちなみにreact-reduxはReactとReduxの仲介役を担っているモジュールです。

$ yarn add redux react-redux

これで開発環境は構築できました。

ファイル構成を整える

srcディレクトリの配下をこんな感じにしておきましょう。
あらかじめフォルダやファイルを作っていくことで、模写がラクになります。

├── App.css
├── App.test.js
├── actions
│   └── index.js
├── components
│   └── App.js
├── index.js
├── reducers
│   ├── count.js
│   └── index.js
└── serviceWorker.js

レッツ模写!

Actionの定義

storeにメッセージを送るためのActionを定義します。

カウントアプリは「+」と「-」ボタンによって状態を変化させるだけですので、必要なアクションは2つのみとなります。

acitons/index.js
export const INCREMENT = 'INCREMENT'
export const DECREMENT = 'DECREMENT'

// 書き方が2通りありますが、どちらでも問題ないです
export const increment = () => {
  return {
    type: INCREMENT
  }
}

export const decrement = () => ({
  type: DECREMENT
)}

Reducerの実装

storeから送られた情報をもとにstateを実際に変更する「Reducer」を実装しましょう。

index.jsの実装

Reducer群を管理するindex.jsを実装します。

今回作成するアプリは1つのReducerしか持たないので、count.jsと分離する必要はありません。
ただ、規模の大きいアプリの場合は必要となりますので、今後の為にもやっておきましょう。

reducers/index.js
import { combineReducers } from 'redux'
import count from './count'

export default combineReducers(({ count }))

count.jsの実装

カウンターの数字を変更する部分となります。
storeから送られる情報の中のaction.typeによって、数字を増やすのか・減らすのかを決めています。

reducers/count.js
import { INCREMENT, DECREMENT } from '../actions'

//コンポーネントの初期値を設定
const initialState = { value: 0 }

export default (state = initialState, action) => {
  switch (action.type) {
    case INCREMENT:
      return { value: state.value + 1 }
    case DECREMENT:
      return { value: state.value - 1 }
    default:
      return state
  }
}

storeの実装

実装されたReducerをもとに、storeを作成します。

index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'

import reducer from './reducers'
import App from './components'
import * as serviceWorker from './serviceWorker'

// 作成されたReducerをもとにstoreを作成
// アプリケーション内部の全てのstateは、このstateに集約される
const store = createStore(reducer)

// Providerによって、storeがどのコンポーネントからも参照できるようになる
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

serviceWorker.unregister();

コンポーネントの実装

index.jsで呼び出している「App」コンポーネントを実装しましょう。

components/App.js
import React, { Component } from 'react'
import { connect } from 'react-redux'

import { increment, decrement } from '../actions'

class App extends Component {
  render() {
    const props = this.props
    return (
      <React.Fragment>
        <div>count:{props.value}</div>
        <button onClick={props.increment}>+</button>
        <button onClick={props.decrement}>-</button>
      </React.Fragment>
    );
  }
}

// stateから必要な情報をコンポーネントにマッピングする関数
const mapStateToProps = state => ({ value: state.count.value })

// dispatch関数をコンポーネントにマッピングする関数
const mapDispatchToProps = dispatch => ({
  increment: () => dispatch(increment()),
  decrement: () => dispatch(decrement())
})

// こんな書き方もある↓
// const mapDispatchToProps = ({ increment, decrement })

// stateとacitonをコンポーネントに関連づける
export default connect(mapStateToProps, mapDispatchToProps)(App)

次は...

TODOリストや、Ajax通信を実装してみるといいかもしれません。

4
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  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
yutaro50

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
4
Help us understand the problem. What is going on with this article?