Learn プログ

-マナビメモ-

Riot.js Redux Rails 4 / 8 「3で作成したformを、title-formタグとして独立させる」

はじめに

フロントにRiot.jsとReduxを使いサーバーサイドにRailsを使い、初めに環境構築し、次にReduxの使い方の流れをみて、最終的に簡単なTodoAppを作成する。

環境構築

簡単な例でReduxの流れをみる

簡単な例でReduxの流れをみる

Todo Appの作成

最終的に完成したTodo App
https://github.com/atfeo/Riot_Redux_Rails

参考

3で作成したformを、title-formタグとして独立させる。

title-formタグの作成

formタグをsample-outputタグから独立させるためのtitle-formタグを作成する。 sample-outputタグからform以下をそのまま持ってくる。

<!-- ./client/src/tags/title-form.tag -->
<title-form>
  <form onsubmit={changeTitle}>
    <input type="text" name="newTitle">
    <input type="submit" value="Change Title">
  </form>

  <script>
    changeTitle() {
      if (!this.newTitle.value) {
        return;
      }
      this.opts.store.dispatch({ type: 'CHANGE_TITLE', data: this.newTitle.value })
      this.newTitle.value = ''
    }
  </script>
</title-form>

sample-outputタグはこのようになる。

<!-- ./client/tags/sample-output.tag -->
<sample-output>
  <h1>{this.opts.store.getState().title}</h1>
</sample-output>

index.jsの書き換え

title-formタグをマウントするためにindex.jsの必要な書き換え等を行う。

// ./client/src/index.js
// 追加
import './tags/title-form.tag';

// 書き換え
document.addEventListener('DOMContentLoaded', () => {
  riot.mount('*', { store: reduxStore });
});

これら以外はそのまま。

index.html.erbに追加

title-formタグの追加

# ./app/views/top/index.html.erb
<sample-output></sample-output>
<title-form></title-form>

ブラウザでlocalhost:5000を更新して確認。 表示は変わらない。 しかし、フォームに入力した文字がタイトルに反映されなくなっている。
Riotではonsubmitなどのイベントハンドラが呼ばれた後、this.update()が自動的に呼ばれるので、sample-outputタグ内にformタグがあった時は{this.opts.store.getState().title}が新しいtitleを取りに行っていた。しかし、独立したタグになったためsample-outputタグではthis.update()が呼ばれず変更が反映されない。(この理解であっているかわからない。)

更新が反映されるようにする

storeにはsubscribe()というメソッドがあり、これはdispatchでactionが送られるたびに呼ばれるらしいので(subscribeについてよく理解できていない。)、これを使う。

<!-- ./client/tags/sample-output.tag -->
<sample-output>
  <h1>{this.opts.store.getState().title}</h1>

  <script>
    this.opts.store.subscribe(() => this.update())
  </script>
</sample-output>

これでタイトルの更新が反映されるようになった。
ブラウザでlocalhost:5000を更新して確認。

リファクタリング

action

今後アクションが増えた時アクションがまとまっていた方が良いのでactions.jsにまとめる。

// ./client/src/actions.js
module.exports = {
  changeTitle,
};

function changeTitle(newTitle) {
  return { type: 'CHANGE_TITLE', data: newTitle };
}

actions.jsにアクションを切り出したのでアクションを使っていた部分を書き換える。

// ./client/src/tags/title-form.tag
<script>
  // 追加
  const actions = require('../actions.js')
  changeTitle() {
    if (!this.newTitle.value) {
      return;
    }
    // 書き換え
    this.opts.store.dispatch(actions.changeTitle(this.newTitle.value))
    this.newTitle.value = ''
  }
</script>

今までと変わらないことをブラウザでlocalhost:5000を更新して確認。

Reduxの使い方の大まかな流れがを確認。次回からはtodoアプリの作成。

Riot.js Redux Rails 5 / 8に続く

Riot.js Redux Rails 3 / 8 「formを追加しtitleの変更を可能にする」

はじめに

フロントにRiot.jsとReduxを使いサーバーサイドにRailsを使い、初めに環境構築し、次にReduxの使い方の流れをみて、最終的に簡単なTodoAppを作成する。

環境構築

簡単な例でReduxの流れをみる

Todo Appの作成

最終的に完成したTodo App
https://github.com/atfeo/Riot_Redux_Rails

参考
+ RiotJS and Redux - Part 2 + Redux入門【ダイジェスト版】10分で理解するReduxの基礎

formを追加しtitleの変更を可能にする

sample-outputタグにformを追加

<!-- ./client/tags/sample-output.tag -->
<h1>{this.opts.store.getState().title}</h1>
<form onsubmit={changeTitle}>
  <input type="text" name="newTitle">
  <input type="submit" value="Change Title">
</form>

これでChange Titleボタンを押すとchangeTitleメソッドが実行されるようになる。

sample-outputタグにscriptを追加

changeTitleメソッドを実装していく。

// ./client/tags/sample-output.tag
</form>

<script>
  changeTitle() {
    if (!this.newTitle.value) {
      return;
    }
    this.opts.store.dispatch({ type: 'CHANGE_TITLE', data: this.newTitle.value })
    this.newTitle.value = ''
  }
</script>

store.dispatch(action)でreducerにdispatchの引数であるactionを渡す。
今回のactionは{ type: 'CHANGE_TITLE', data: this.newTitle.value }

Reducerでのactionの処理

受け取ったactionのtypeによって新しいstateを返すように書き換える。

// ./client/src/index.js
function reducer(state = { title: 'Default title' }, action) {
  switch (action.type) {
    case 'CHANGE_TITLE': {
      const newState = { title: action.data };
      return newState;
    }
    default:
      return state;
  }
}

これでDefault Titleをフォームに入力した文字に変更出来るようになったので、ブラウザでlocalhost:5000を更新して確認。

リファクタリング

// ./client/src/index.js
function reducer(state = { title: 'Default title' }, action) {
  switch (action.type) {
    case 'CHANGE_TITLE':
      return Object.assign({}, state, { title: action.data });
    default:
      return state;
  }
}

このようにしておくとstateにtitleの他にbody等がある時({ title: ~, body: ~ })、リファクタリング前だとbodyも改めて書かないとtitleだけになってしまうが、リファクタリング後はbodyを書かなくてもtitleだけ変更出来る。

Riot.js Redux Rails 4 / 8に続く

Riot.js Redux Rails 2 / 8 「Reduxを使ってtitleを表示させる」

はじめに

フロントにRiot.jsとReduxを使いサーバーサイドにRailsを使い、初めに環境構築し、次にReduxの使い方の流れをみて、最終的に簡単なTodoAppを作成する。

環境構築

簡単な例でReduxの流れをみる

Todo Appの作成

最終的に完成したTodo App
https://github.com/atfeo/Riot_Redux_Rails

参考

Reduxを使ってtitleを表示させる

Reducer

まずindex.jsに

// ./client/src/index.js
function reducer(state, action) {
  return state;
}

を追加しreducerを作成。reducerはactionを受けてstateを変更するメソッド。
reducerのstateにデフォルトの値を設定。

// ./client/src/index.js
function reducer(state = { title: 'Default title' }, action) {
  return state;
}

Store

次にindex.jsに

// ./client/src/index.js
import { createStore } from 'redux';

const reduxStore = createStore(reducer);

を追加しreduxStoreオブジェクトを作成。(オブジェクトで合っているかわからない。)

tagにStoreを渡す

作成したreduxStoreオブジェクトをstoreという名前でtagに渡す。

// ./client/src/index.js
document.addEventListener('DOMContentLoaded', () => {
  riot.mount('sample-output', { store: reduxStore });
});
tagに渡されたStoreからtitleを取り出す

sample-outputタグを次のように書き換える。

<!-- ./client/tags/sample-output.tag -->
<sample-output>
  <h1>{this.opts.store.getState().title}</h1>
</sample-output>

this.opts.storeでreduxStoreオブジェクトにアクセス。
reduxStoreオブジェクトの持つgetState()というメソッドでreducerで定義したstateにアクセスできる。
stateには{ title: 'Default title' }という値が設定されているのでlocalhost:5000を更新するとHello Riot Redux RailsからDefault title に表示が変わる。

Riot.js Redux Rails 3 / 8に続く