初心者のプログラミング日記

プログラミング初心者の日記

プログラミングに関することを書いていきます。

ReactとReduxでカウンターアプリを作る

今回はReactとReduxで簡単なカウンターアプリを作ってみます。
Reduxを学んで3日目なので間違っているかもしれません。
Reduxを使うにはまず以下のコマンドでReduxに必要なモジュールをインポートしておきます。

npm install redux
npm install react-redux

ファイル構成はsrc内に以下のファイルがあります。
・Actions.js
・Reducres.js
・index.js
・App.js

まずActions.jsから書いていきます。

//Actions.js
//Action type
const INCREMENT="INCREMENT";
const DECREMENT="DECREMENT";

//Action Creater
const increment =()=>{
    return{type:INCREMENT};
};

const decrement =()=>{
    return{type:DECREMENT};
};

export {increment,decrement};
export {INCREMENT,DECREMENT};

ここにはAction typeとAction Creatorをかいてあります。書き方はたくさんあり以下の書き方でも大丈夫です。好きな書き方を選んでください。

//typeに直接書く
const increment =()=>{
    return type:”INCREMENT”;
};

const decrement =()=>{
    return type:"DECREMENT”;
};

//関数で書く
function increment(){
    return{type:INCREMENT};
}

function decrement(){
    return{type:DECREME};
}

ちなみにtypeはconstで定数化するのがツウらしいので今回はそうしてあります。

次はReducres.jsを書いていきます。

//Reducres.js
import { combineReducers } from "redux";
import {INCREMENT,DECREMENT} from './Action';

const initialState = { count: 0 };

//Reducer
const counter = (state = initialState, action) => {
  switch(action.type){
    case INCREMENT:
      return {
        ...state,
        count: state.count + 1} 
    case DECREMENT:
      return {
        ...state,
        count: state.count - 1}
    default:
      return state
  }
}

const  reducers=combineReducers({counter});
export default reducers;

Reducers.jsにはReducerを書いています。
Reducerはswitch文を使ってActionごとに処理を実行します。
Reactではstateを直接変更してはいけないルールがあるのでコピーしてから変更します。
本来combineReducersは複数のReducerをまとめるために使うのですが、慣れるために今回は使っています。

次にindex.jsを書いていきます。

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux'; 
import { Provider } from 'react-redux';
import App from './App';
import reducers from './Reducres';
import * as serviceWorker from './serviceWorker';
 
const  store = createStore(reducers);
 
ReactDOM.
render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
serviceWorker.unregister();

creatStoreでStoreを作ります。引数には先程作ったReducerをいれます。
そして、コンポーネントでラップすることで、storeのデータを渡すことができます。

最後にApp.jsを書いていきます。

//App.js
import React from 'react';
import { connect } from 'react-redux'
import { increment, decrement } from './Action';

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

  const mapStateToProps = (state) =>{
    return {count: state.counter.count}
  }
  
  const mapDispatchToProps = (dispatch) =>(
    {
      increment: () => dispatch(increment()),
      decrement: () => dispatch(decrement())
    }
  )
  
  export default connect(mapStateToProps, mapDispatchToProps)(App);

mapStateToPropsではstateをpropsに変換して返します。
今回はReducerのcounter関数のcountというstateが欲しいのでこのように書いています。
mapDispatchToPropsではdiapatchを使うために書いてあります。とりあえず、何かしらのアクション(カウント増やす、減らすなど)をする場合には書いておけば大丈夫だと思います。
diapatchの引数にはAction Creatorを入れることで、その情報がcreateStoreで登録したreducerに送られ、Action typeごとに処理を実行します。ここは自己解釈なので正しいかはわかりません。
最後のconnectコンポーネントを引数にいれ、mapStateToProps, mapDispatchToPropsを引数のコンポーネントと結びつけています。

本当はApp.jsは描画するだけのコンポーネントにしたかったのですが、connect関数やmapStateToProps を別のファイルに分けてApp.jsに読み込ませる方法がわからなかったのでこのようにしました。分ける方法が分かったら追記するかもしれません。

これで終わりです。

追記:GitHubに挙げときました。Gitとかの使い方が分からなかったのでソースコードのみになります。
https://github.com/matsudasan/counter