tag:crieit.net,2005:https://crieit.net/tags/Flux/feed
「Flux」の記事 - Crieit
Crieitでタグ「Flux」に投稿された最近の記事
2018-10-30T08:24:51+09:00
https://crieit.net/tags/Flux/feed
tag:crieit.net,2005:PublicArticle/14563
2018-10-09T21:54:48+09:00
2018-10-30T08:24:51+09:00
https://crieit.net/posts/Vuex-Store-Nuxt
VuexのStoreはNuxt.jsのマニュアルを見るとすぐ理解できる
<p>最近のJavaScriptのフレームワークを勉強したての人の場合、Vue.jsなどはすぐ理解できても、Fluxの概念やVuexのStore等でわからなくなってしまうことはありませんか? そういう場合、Nuxt.jsを触りつつNuxt.jsのマニュアルを見ると非常に簡潔で理解しやすいです。</p>
<p>具体的には下記のページです。ここを参考にしながら説明していきます。先にリンクの説明を見たい場合は「モジュールモード」の方を見るとより分かりやすいと思います。当記事の内容もそちらをベースに進めていきます。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://ja.nuxtjs.org/guide/vuex-store/">Vuex ストア - Nuxt.js</a></p>
<h2 id="そもそも何に使うものなのか?"><a href="#%E3%81%9D%E3%82%82%E3%81%9D%E3%82%82%E4%BD%95%E3%81%AB%E4%BD%BF%E3%81%86%E3%82%82%E3%81%AE%E3%81%AA%E3%81%AE%E3%81%8B%EF%BC%9F">そもそも何に使うものなのか?</a></h2>
<p>Storeはアプリケーション全体の状態を管理してくれるものです。具体的にはログインしているユーザーの情報などが一番わかり易いと思います。</p>
<h2 id="具体的にどうやって使うのか"><a href="#%E5%85%B7%E4%BD%93%E7%9A%84%E3%81%AB%E3%81%A9%E3%81%86%E3%82%84%E3%81%A3%E3%81%A6%E4%BD%BF%E3%81%86%E3%81%AE%E3%81%8B">具体的にどうやって使うのか</a></h2>
<p>Nuxt.jsの場合、まず <code>store/index.js</code> に状態の定義を行います。</p>
<pre><code class="javascript">export const state = () => ({
user: null
})
</code></pre>
<p>また、その下に上記の状態を更新するための mutation という処理を書きます。</p>
<pre><code class="javascript">export const mutations = {
login(state, user) {
state.user = user
},
logout(state) {
state.user = null
}
}
</code></pre>
<p>上記のようなファイルを作っておけばNuxt.jsでは勝手に読み込まれます。</p>
<p>あとは適当などこかのコンポーネント内で上記のmutationを呼び出せば状態を更新できます。</p>
<pre><code class="javascript">this.$store.commit('login', user)
</code></pre>
<p>コンポーネント内で参照したい時は下記のようになります。</p>
<pre><code class="javascript"><span><span>{</span><span>{</span> $store.state.user.name <span>}</span><span>}</span></span>
</code></pre>
<p>非常に簡単ですね。</p>
<h2 id="何のメリットがあるか?"><a href="#%E4%BD%95%E3%81%AE%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88%E3%81%8C%E3%81%82%E3%82%8B%E3%81%8B%EF%BC%9F">何のメリットがあるか?</a></h2>
<p>アプリケーション上のどこからでもアクセスできるというのが一番のメリットとしてあげられるのではないかと思います。今回の例ではいちいち下層のコンポーネントにユーザー情報をプロパティ経由で渡さなくても、ユーザー情報にアクセスできます。</p>
<p>例えばStoreを使っていない場合、全体の <code>layout.vue</code> がありそこにユーザー情報を持たせるとすると、そこから <code>TheHeaderNavi</code> にユーザー情報をプロパティで渡し、更にその中の <code>TheLoginButton</code> 、更にその中の <code>TheLoginModal</code> にユーザー情報を渡さなければなりません。</p>
<p>しかもTheLoginModalでログインしたら、 <code>@logined</code> のようなイベントでログインした情報を受け取るというバケツリレーを最初に戻るまで繰り返さなければなりません。しかも他のページ上の画面でもユーザー情報を表示したいところがあれば全部同様にしていかなければなりません。気が狂いそうなほど非常に面倒です。</p>
<p>Storeであればこれらは全部不要となります。開発者の負担がまるで違いますので、超小規模アプリケーション以外ではほぼ必須ではないかと思います。</p>
<h2 id="Nuxt.jsの場合ファイル分けも非常に簡単"><a href="#Nuxt.js%E3%81%AE%E5%A0%B4%E5%90%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%88%86%E3%81%91%E3%82%82%E9%9D%9E%E5%B8%B8%E3%81%AB%E7%B0%A1%E5%8D%98">Nuxt.jsの場合ファイル分けも非常に簡単</a></h2>
<p>ユーザー情報だけでなく、例えばチャットのページでは発言一覧、地図のページでは地図上のマーカー情報一覧などをStoreに置いておきたいところなども出てくると思います。この場合先程紹介したマニュアルのページで解説されていますが、用途ごとにファイルを分けることもNuxt.jsでは非常に簡単です。</p>
<p>具体的にどうするかというと、本当にただファイルを分けて定義するだけです。例えば <code>store/chat.js</code> を作るとすると、参照する時は</p>
<pre><code class="javascript"><div v-for="post in $store.state.chat.posts" :key="post.id">
</div>
</code></pre>
<p>のような感じで、commitは</p>
<pre><code class="javascript">this.$store.commit('chat/add', post)
</code></pre>
<p>という感じで、非常に簡単です。</p>
<h2 id="ReactのReduxと比較すると?"><a href="#React%E3%81%AERedux%E3%81%A8%E6%AF%94%E8%BC%83%E3%81%99%E3%82%8B%E3%81%A8%EF%BC%9F">ReactのReduxと比較すると?</a></h2>
<p>ReactのReduxを使ったことがある方は分かると思いますが、結構面倒です(とはいえそれでもプロパティで数珠つなぎにするよりははるかに楽ですが)。だいぶ前に同様の記事を書いています。そこでは概念しか書いていませんが実際に実装すると結構手間で、管理も大変です。</p>
<p><a href="https://crieit.net/posts/React-Redux">ReactにReduxを組み合わせると何が楽なのか</a></p>
<p>それに比べNuxt.jsのマニュアルになり、ぐんとわかりやすくなっていると思います。Reduxだと他にもactionsとかreducerとかファイル数も多く、面倒になっている部分だと思います。Nuxt.jsだと先程の説明ではstateとmutationsしか出てきておらず、最小限の実装だとほんとうに単純明快です。</p>
<p>もちろんこの簡単さのために逆に犠牲にしている部分はあると思うのですが、それでも個人であれこれぱぱっと何か作りたいときになどにはこれくらいで十分でスピーディーに物事を進められると思います。</p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>とにかくこのNuxt.jsのStoreから理解を進めていくと簡単で分かりやすいです。多分ここを読んでちらっと理解しておくと、VuexやReactでStoreを使う時なども多少理解しやすくなっていると思います。</p>
<p>今までよく理解できなかった、という方がいればぜひこの機会にもう一度確認してみてください。</p>
だら@Crieit開発者
tag:crieit.net,2005:PublicArticle/14296
2016-08-22T23:02:13+09:00
2018-10-31T18:32:18+09:00
https://crieit.net/posts/React-Redux
ReactにReduxを組み合わせると何が楽なのか
<p>React + Reduxを使うとどうメリットがあるかというと、色々とあるとは思う。<br />
ただ、どう楽になるのかというのに焦点をおいてみる。</p>
<h3 id="Reactのみの例"><a href="#React%E3%81%AE%E3%81%BF%E3%81%AE%E4%BE%8B">Reactのみの例</a></h3>
<p>下記のようなコンポーネント構成のアプリケーションを作成するとする。</p>
<ul>
<li>コンテナ : App
<ul>
<li>ヘッダ : Header</li>
<li>ログインボタン : Login(ログイン時はユーザー名表示)</li>
<li>コンテンツ : Contents</li>
</ul></li>
</ul>
<p>Reactのみだと関連箇所は下記のようなjsxになるだろう。</p>
<p>App</p>
<pre><code class="javascript"><div>
<Header
user={this.state.user}
onLogined={this.onLogined}
/>
<Contents
user={this.state.user}
contents={this.state.contents}
/>
</div>
</code></pre>
<p>Header</p>
<pre><code class="javascript"><div>
<Login
user={this.props.user}
onLogined={this.props.onLogined}
/>
</div>
</code></pre>
<p>Login</p>
<p>handleLoginでサーバーへのログインリクエストを行い成功したらthis.props.onLoginedを呼び出す。</p>
<pre><code class="javascript"><div>
<button onClick={this.handleLogin}>ログイン</button>
</div>
</code></pre>
<p>共通で使用される値は一番上の階層で扱うのが望ましいので、<br />
見ての通りuserとonLoginedをひたすらプロパティで引き継ぎまくる事になってしまう。<br />
Reactの良さを理解してもこのあたりでうんざりしてくる。</p>
<h3 id="React + Reduxにすると"><a href="#React+%2B+Redux%E3%81%AB%E3%81%99%E3%82%8B%E3%81%A8">React + Reduxにすると</a></h3>
<p>プロパティでの指定が不要になる。<br />
簡単なログアウトボタンの例は下記の様になる。<br />
(actionやreducer等の細かい部分の解説は省く)</p>
<pre><code class="javascript">import React from 'react';
import { connect } from 'react-redux';
import request from 'superagent';
import { setUser } from '../../actions/main';
function mapDispatchToProps(dispatch) {
return {
handleLogin: (user) => dispatch(setUser(user)),
};
}
class Logout extends React.Component {
handleSubmit(e) {
request.post('/logout')
.end((err, res) => {
if (!err) {
this.props.handleLogin(null);
}
});
}
render() {
return (
<button onClick={this.handleSubmit}>ログアウト</button>
);
}
}
export default connect((state) => state, mapDispatchToProps)(Logout);
</code></pre>
<p>上記のようにコールバックのプロパティもその場で決められる。<br />
また、下記のように、ヘッダー側のユーザー情報表示もuserを引き継がなくても取得できる。<br />
(connectにより勝手にpropsに入っている)</p>
<pre><code class="javascript">import React from 'react';
import { connect } from 'react-redux';
import Login from './login';
import Logout from './logout';
import { setUser } from '../../actions/main';
class Header extends React.Component {
renderUser() {
if (this.props.user == null) {
return <Login />;
}
return (
<div>
こんにちは{this.props.user.name}さん
<Logout />
</div>
);
}
render() {
const user = this.renderUser();
return (
<div>
<h1>タイトル</h1>
{user}
</div>
);
}
}
export default connect((state) => state)(Header);
</code></pre>
<h3 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h3>
<p>どんどん細かくコンポーネントするのがよい、ということのはずだがそれをデメリットに変えてしまう自己矛盾したプロパティの仕組み。<br />
Reduxによってそれが解消され使い勝手の良い物になる。<br />
極小アプリケーションでない限りはほぼ必須であると思われる。</p>
だら@Crieit開発者