Riot.js Redux Rails 4 / 8 「3で作成したformを、title-formタグとして独立させる」
はじめに
フロントにRiot.jsとReduxを使いサーバーサイドにRailsを使い、初めに環境構築し、次にReduxの使い方の流れをみて、最終的に簡単なTodoAppを作成する。
環境構築
- Riot.js Redux Rails 1 「環境構築」
簡単な例でReduxの流れをみる
- Riot.js Redux Rails 1 / 8 「環境構築」
簡単な例でReduxの流れをみる
- Riot.js Redux Rails 2 / 8 「Reduxを使ってtitleを表示させる」
- Riot.js Redux Rails 3 / 8 「formを追加しtitleの変更を可能にする」
- Riot.js Redux Rails 4 / 8 「3で作成したformを、title-formタグとして独立させる」
Todo Appの作成
- Riot.js Redux Rails 5 / 8 「Todoリストを表示する」
- Riot.js Redux Rails 6 / 8 「新たなTodoを追加出来るようにする」
- Riot.js Redux Rails 7 / 8 「完了したTodoをチェック出来るようにする」
- Riot.js Redux Rails 8 / 8 「チェックしてあるタスクを削除出来るようにする」
最終的に完成した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 3 / 8 「formを追加しtitleの変更を可能にする」
はじめに
フロントにRiot.jsとReduxを使いサーバーサイドにRailsを使い、初めに環境構築し、次にReduxの使い方の流れをみて、最終的に簡単なTodoAppを作成する。
環境構築
- Riot.js Redux Rails 1 / 8 「環境構築」
簡単な例でReduxの流れをみる
- Riot.js Redux Rails 2 / 8 「Reduxを使ってtitleを表示させる」
- Riot.js Redux Rails 3 / 8 「formを追加しtitleの変更を可能にする」
- Riot.js Redux Rails 4 / 8 「3で作成したformを、title-formタグとして独立させる」
Todo Appの作成
- Riot.js Redux Rails 5 / 8 「Todoリストを表示する」
- Riot.js Redux Rails 6 / 8 「新たなTodoを追加出来るようにする」
- Riot.js Redux Rails 7 / 8 「完了したTodoをチェック出来るようにする」
- Riot.js Redux Rails 8 / 8 「チェックしてあるタスクを削除出来るようにする」
最終的に完成した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 2 / 8 「Reduxを使ってtitleを表示させる」
はじめに
フロントにRiot.jsとReduxを使いサーバーサイドにRailsを使い、初めに環境構築し、次にReduxの使い方の流れをみて、最終的に簡単なTodoAppを作成する。
環境構築
- Riot.js Redux Rails 1 / 8 「環境構築」
簡単な例でReduxの流れをみる
- Riot.js Redux Rails 2 / 8 「Reduxを使ってtitleを表示させる」
- Riot.js Redux Rails 3 / 8 「formを追加しtitleの変更を可能にする」
- Riot.js Redux Rails 4 / 8 「3で作成したformを、title-formタグとして独立させる」
Todo Appの作成
- Riot.js Redux Rails 5 / 8 「Todoリストを表示する」
- Riot.js Redux Rails 6 / 8 「新たなTodoを追加出来るようにする」
- Riot.js Redux Rails 7 / 8 「完了したTodoをチェック出来るようにする」
- Riot.js Redux Rails 8 / 8 「チェックしてあるタスクを削除出来るようにする」
最終的に完成した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
に表示が変わる。