unistore が気になる
frontend handbook 2018 で発掘しました。tiny ~650b、軽量な状態管理ライブラリで Redux 風です。ReduxDevtool がそのまま使えます。イベント駆動さながら、ボイラープレートを上手く隠蔽しています。「Redux の良さは欲しいが、現場の学習・運用コストを加味すると悩ましい…だけどデコレーター利用する状態管理も遠慮したい…」みたいな悩みを抱えてる人には良い落とし所かもしれません。作者は preact の人です。
actions を定義し、Provider/connect 経由でコンポーネントに注入し、発火させると状態が変化します。mapStateToProps/mapDispatchToProps に似た I/Fも明らかに Redux に寄せています。preact と React のバインダ入りです。
import createStore from 'unistore'
import { Provider, connect } from 'unistore/preact'
let store = createStore({ count: 0 })
// If actions is a function, it gets passed the store:
let actions = store => ({
// Actions can just return a state update:
increment(state) {
return { count: state.count+1 }
},
// The above example as an Arrow Function:
increment2: ({ count }) => ({ count: count+1 }),
//Actions receive current state as first parameter and any other params next
//check this function as <button onClick={incrementAndLog}>
incrementAndLog: ({ count }, event) => {
console.info(event)
return { count: count+1 }
},
// Async actions can be pure async/promise functions:
async getStuff(state) {
let res = await fetch('/foo.json')
return { stuff: await res.json() }
},
// ... or just actions that call store.setState() later:
incrementAsync(state) {
setTimeout( () => {
store.setState({ count: state.count+1 })
}, 100)
}
})
const App = connect('count', actions)(
({ count, increment }) => (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
)
)
export default () => (
<Provider store={store}>
<App />
</Provider>
)
所感
Redux 運用の辛さをチラホラ見かける昨今。それの利点を落とさずに、どう現場に落とし込むかという課題の表れが、こういったライブラリが生まれるルーツだと思います。
middleware 不要で非同期処理をサラッと書けるので、要件次第では良い選択肢かなと思います。サイズが小さいため、srcコードを眺めるのもまた楽しいです。actions の中の煩雑な処理は immer で書くと幸せになれそうです。