【WIP】react-reduxのdocksを使って簡単なメモ帳アプリを作る

今回はreact-reduxのdocksというデザインパターンを使って簡単なメモ帳アプリを作っていきます。

超簡単(一言で)にreact, redux, docksの説明します。

  • react
  • redux
  • docks:
  • react-redux

今回はtodoリストよりシンプルな以下のようなアプリを作っていきます。

各種インストール

まずnode jsがインストールされている

次にReactプロジェクトのテンプレートを作成する

npx create-react-app react-redux-app

ReduxをReactで使うためのライブラリのインストール

npm install --save react-redux

(エラーでひっかかったらsudo付けてみてください)

実装

moduleの作成

docksではaction_type,action_creater,reducer をmoduleという単位で扱います。

今回はメモに関するaction_type,action_creater,reducerをここにいれます。

では、moduleを作っていきます。

ディレクトリを作成します。

mkdir module && cd module

moduleの中に

let nextMemoId = 0;

// action
const ADD_MEMO = 'ADD_MEMO';

//action creator
export const actionCreaters = {
  addMemo: text => ({
    type: 'ADD_MEMO',
    id: nextMemoId++,
    text,
  }),
};

// reducer
export default function reducer(state = [], action) {
  switch (action.type) {
    case ADD_MEMO:
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false,
        },
      ];
    default:
      return state;
  }
}

action_createrでは, actionの名前やactionに必要な情報が格納されている
オブジェクトを生成します。

reducerは受け取ったstateとactionを使って新しいstateを生成します。

reducerはdispatchされた場合にその処理を行います。

次にmodule/index.jsを以下のように作ります。

import memoReducer from './memo';

export default {
  memo: memoReducer,
};

をつくります。
module/index.jsを作ることによって
外部からmoduleをimportする場合にindex.jsにexportされたモジュールを取得します。

containers, compornentsの作成

次にcontainersとcompornentsを作成します。
まずはディレクトリを作成しておきます。

mkdir src/containers
mkdir src/compornents

ファイルをどんどん書いていきます。
(ちなみにデフォルトではsrc/App.jsとなっていますが消すか、このディレクトリに移動してください)
src/compornents/App.js

import React, { Component } from 'react';
import '../App.css';
import AddMemo from '../containers/AddMemo';
import VisibleMemoList from '../containers/VisibleMemoList';

class App extends Component {
  render() {
    return (
      
); } } export default App

srs/compornents/Form.js

import React from 'react';
import Button from '@material-ui/core/Button';

export default class Form extends React.Component {
  render() {
    return (
      <form
        className="addMemo"
        onSubmit={e => {
          e.preventDefault();
          if (!this.refs.inputText.value.trim()) {
            return;
          }
          this.props.addMemo(this.refs.inputText.value);
          this.refs.inputText.value = '';
        }}
      >
        <input type="type" className="addMemo_input" ref="inputText" />
        <Button
          variant="contained"
          color="primary"
          style={{ marginLeft: '20px' }}
          onClick={() => this.props.addMemo(this.refs.inputText.value)}
        >
          追加
        </Button>
      </form>
    );
  }
}

srs/compornents/Memo.js

import React from 'react';
import Card from '@material-ui/core/Card';

export default class Memo extends React.Component {
  render() {
    return (
      
        
{this.props.text}
); } }

srs/compornents/MemoList.js

import React from 'react';
import Memo from './Memo';
import Card from '@material-ui/core/Card';

export default class MemoList extends React.Component {
  render() {
    console.log('MemoList');
    console.log(this.props);
    return (
      <Card className="memoList">
        <h2 className="memoList_title">TODO</h2>
        <div className="notCompleted">
          {this.props.memos.map(memo => (
            <Memo key={memo.id} toggleMemo={this.props.toggleMemo} {...memo} />
          ))}
        </div>
      </Card>
    );
  }
}

containersも同様に

import { connect } from 'react-redux';
import { actionCreaters } from '../modules/memo';
import Form from '../components/Form';

const mapDispatchToProps = dispatch => {
  return {
    addMemo: text => dispatch(actionCreaters.addMemo(text)),
  };
};

export default connect(null, mapDispatchToProps)(Form);

src/containers/VisibleMemoList.js

import { connect } from 'react-redux';
import memoListModule from '../modules/memo';
import MemoList from '../components/MemoList';

const mapStateToProps = state => {
  console.log('mapStateToProps');
  console.log(state);
  return {
    memos: state.memo,
  };
};

const mapDispatchToProps = dispatch => {
  return {
    toggleMemo: id => dispatch(memoListModule.toggleMemo(id)),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(MemoList);

最後にsrc/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
import * as serviceWorker from './serviceWorker';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import reducer from './modules';

console.log(reducer);

const store = createStore(
  combineReducers({
    ...reducer,
  })
);

console.log(store);
console.log(store.getState());

ReactDOM.render(
  
    
  ,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
タイトルとURLをコピーしました