##ほんとにめっちゃ使いやすいので早く使ってください
いつまでReduxでヒイヒイ言ってるんですか?
Unduxって?
Reactの状態管理をするため(バケツリレーとかしたくない)のライブラリ
公式:undux
###特徴
- ただ使うだけならgetとsetしか存在しない優しい世界
- ただし、rxjsを利用すれば複雑なこともできる
- (僕は)基本的にReactの各ComponentのStateで状態管理するという概念にあっている(と思う)
とりあえずコードを見てくれ
今回つくるのは簡単なチャットアプリのモックだと思ってください
チャットアプリの全ソース:socket_test
まずunduxのインストールから
npm install --save rxjs undux
そして使い方は簡単
まずは保存したい値を入れるStoreを作る
import { createConnectedStore } from 'undux'
var store = createConnectedStore({
comments: [],
user: {
name: null
}
});
export default store;
次にStoreをpropに渡すためにルートのコンポーネントを囲う
(今回はルーターにreact-routerを使ってます)
import React from "react";
import ReactDom from "react-dom";
import { BrowserRouter } from "react-router-dom";
import Store from "./Store";
//router
import App from "./App";
class Root extends React.Component {
render() {
return (
<Store.Container>
<BrowserRouter>
<App />
</BrowserRouter>
</Store.Container>
);
}
}
ReactDom.render(<Root />, document.getElementById("root"));
そしたらStoreを呼び出したいコンポーネントをwithStore
でラップ
import React from "react";
import Store from "../Store";
class Chat extends React.Component {
constructor(props) {
super(props);
this.state = {
msg: "",
comments: []
}
}
componentDidMount() {
}
changeTxt(e) {
this.setState({ msg: e.target.value });
}
render() {
var messages = this.state.comments.map((comment, index) => {
return <p key={index}>{comment.msg}</p>
});
return (
<div>
<input type="text" value={this.state.msg} onChange={(e) => {
this.changeTxt(e);
}} />
<button onClick={() => {
actions.sendMsg(this.props.store, this.state.msg);
this.setState({ msg: "" });
}}>
投稿
</button>
<div>
{messages}
</div>
</div>
);
}
}
export default Store.withStore(Chat);
Storeの値はthis.props.store
から.get("key")
すればとれますが、このまま使うと値の更新時にレンダリングしてくれなくなってしまうのでComponentWillMount
内で監視して、値自体はstate
のものを使います。
componentDidMount() {
var store = this.props.store;
//stateにstoreの値をbind
store.on("comments").subscribe((comments) => {
this.setState({ comments: comments });
});
}
rxjs知らない人のために補足。
クリックイベントなどと同様に、onで値の変更を監視して、subscribeで変更があった時の挙動の制御をします。
後は各々好きなところで値を受け取ってセットすればいい。
僕は個人的にActionファイルは作りたい派なので下記のような構造になった。(Socketわからない人ごめんなさい、普通にComponentWillMount
内でAPIにデータ取りに行ってると思ってもらって構いません。)
componentDidMount() {
var store = this.props.store;
socket.on('entered', (data) => {
var comments = store.get("comments");
comments.push(data);
store.set("comments")(comments);
});
socket.on('received', (data) => {
var comments = store.get("comments");
comments.push(data);
store.set("comments")(comments);
});
socket.on('leaved', (data) => {
var comments = store.get("comments");
comments.push(data);
store.set("comments")(comments);
});
//stateにstoreの値をbind
store.on("comments").subscribe((comments) => {
this.setState({ comments: comments });
});
}
import socket from "../socket";
export const entry = (store, name) => {
var user = store.get("user");
user.name = name;
store.set("user")(user);
const data = { name: name };
socket.emit('connected', data);
}
export const sendMsg = (store, msg) => {
const name = store.get("user").name;
const data = {
name: name,
msg: msg
};
var comments = store.get("comments");
comments.push({ msg: name + " : " + msg });
store.set("comments")(comments);
socket.emit('sendMsg', data);
}
ちなみにプロダクト作る際はもっと複雑にStore使うことになると思うのですが、その際はNamedStore使うと便利です。
import { createConnectedStoreAs } from "undux";
const initialA = {
aHoge:null,
aFuga:null
}
const initialB = {
bHoge:null,
bFuga:null
}
const store = createConnectedStoreAs({
A: initialA,
B: initialB
});
export default store;
こんな形で書いてあげれば、**Store.withStores
**で囲ってあげればそれぞれthis.props.A
, this.props.B
といった形でそれぞれのstoreが下りてきます。
※公式のExampleにはwithStore
って書いてあるので注意。PR送ったのでそのうち治るはず。
よかったこと、悪かったこと
正直、とても使いやすくて、
- 学習コストなんてない(rxjsの勉強はしたほうがいいかも)
- 値の監視
- state内でちゃんと管理できる
- 使うのにミドルウェアいらない
- onとsubscribe使えばvue.jsとかmobxみたいなComputedも実現できる(unduxではEffectって言う)
- ライブラリ内部のコードが見やすい(大体定義にジャンプすれば解決する)
といったあたりがほんとに好きでした。
悪かったことは
- 公式リファレンスがもう少し充実するといい
- まだ出たばかりなので資料が少ない(それでも全然困らないレベルなのはほんとにシンプル目指してるだけあるすごい)
- 値の監視の部分が少し冗長な感じはする
といったあたりでしょうか?
個人的にはstateの値を使ってきれいなReactが書けるので気に入っています。
Reduxとかだと自動でレンダリング走らせてくれたりするので、propsの値を直で使ったりしがちなのが今まではまりやすいポイントだったのかなと思ったので。
あとは、Storeには共通の値を入れといて各コンポーネントで加工して使うとかやりやすそう。
みんなもundux使ってハッピーになりましょう。