Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

Flux Utils のストアをいい感じに hooks で扱う

https://github.com/Fieldscope/flux-hooks を参考にしつつ、型をつけたり型推論が効きやすいように調整したりしてます。

export const useFluxStore = <
  TStore extends ReduceStore<TState, unknown>,
  TState = ReturnType<TStore['getState']>
>(
  store: TStore,
  reducer: (store: TStore) => TState = store => store.getState(),
  deps: unknown[] = []
): TState => {
  const [out, dispatch] = useReducer(
    (_, store) => reducer(store),
    reducer(store)
  );

  useMemo(() => {
    dispatch(store);
  }, deps);

  useEffect(() => {
    const token = store.addListener(() => dispatch(store));
    dispatch(store);

    return () => token.remove();
  }, [store]);
  return out;
};

使う方は非常にカンタンです。これだけ。

const state = useFluxStore(Store);

注意: destructuring してはいけない

型推論がうまく働かなくなるので destructuring はしないでください。

const {foo: hoge, bar: fuga} = useFluxStore(Store); // hoge と fuga はどちらも any になってしまう

一旦変数に格納した後であれば destructuring しても問題ありません。

const store = useFluxStore(Store);
const {foo: hoge, bar: fuga} = store; // これなら OK

const hoge = useFluxStore(Store).foo; // これも問題なし

僕の TS 力ではこれが限界でした……

再利用可能にするのって意味なくない?

"再利用可能になった" はわかる。テストを書きやすいように書くと自然とそうなるから。でも、"再利用可能にしよう" がわからない。YAGNI(You ain't gonna need it)に反しているし、モジュールの安定度を上げる行為だからもっと慎重になるべきだ。そもそも、再利用する理由が同じでないのに再利用する危険性もある。

たとえば Button コンポーネントを考える。かなり汎用的な名前なので様々な場所で"使われてしまう"。結果、Button コンポーネントを変更しようとすると多くの場所に影響が出るようになる。こうなると Button は安易に変更ができない=安定度が高いコンポーネントとなる。

逆に、DangerButton コンポ―ネントを考える。このボタンは「キャンセル」や「削除」など取り消しがつかない操作をするときに使うボタンだ。このとき、DangerButton にデザイン変更が入ったとする。すると DangerButton を変えるだけで全箇所に変更が反映される。この場合は変更したい理由が同じだからOKだ(もちろん Button の場合も理由が同じであれば問題はないのだけれど、得てして Button は IconButton などに派生して使われがちなので理由が同じかどうかを判断するのが難しいことが多い)。

再利用可能にしなければ変更理由が同じコンポーネントをまとめることができないので、再利用可能に"結果としてなる"ことは多い。が、再利用したいから再利用可能にしようはちょっと待って欲しい。それは YAGNI に反しているのではないだろうか?

スタンディングデスクレビュー

FlexiSpot e8を買ったのでレビュー

結論

メチャ最高

  • スタンディングがとにかく楽
  • 上げ下げがボタン一つでできて楽
  • グラつきもない

とりあえず不満点はほぼない。価格も高すぎるって訳でもない。心なしか腰痛も治ってる気がする。

(腰痛が改善してもマイナスがゼロになるだけだから改善した感覚が得づらい)

買ってから気づいたが、立った状態と座った状態だと見やすいディスプレイの高さが微妙に違うのでモニターアームは必須かもしれない(我慢できないほどではない)

ここが惜しい

机の下にコード収納が一応あるのだが、これがネジ式になっていて結構めんどい。ネジを外してから落ちないように抑えつつネジを留める必要がある。配線をこまめに変える人はやめた方がいいかもしれない。

あと、デフォルトの天板にしたんだけど、角の部分の処理が甘くてチクチクする。そこまで致命的ではないけどたまに気になる。個体差があるかもなので、俺がハズレを引いただけかもしれない。

まあでもマジでそれくらいで不満点はほとんどない。

React でテストしているときに You might have mismatching versions of React and the renderer と出たときの対処法

jest.resetModules() などの関係でこのエラーが出ることがあります。そういうときにごり押すハックを編み出したので紹介します。

jest.mock('react', () => jest.requireActual('react'));

それがこちらです。こうすることで jest.resetModules や jest.isolateModules を使ったとしても import 'react'; でインポートされるモジュールが一意に定まります。

スーパーで荷物をカゴ→カバンと移し替えるときはハノイの塔を思い出せ

スーパーで買い物をしたとき、店員さんがまずカゴに詰めてくれます。店員さんは気を遣って下に重いもの、上に軽いものというように積んでくれますが、カゴはFILO(先入れ後出し)なので、上から順にカバンに詰めると今度は下に軽いもの、上に重いものが来てしまいます。

これを解消するにはどうしたら良いのでしょうか?

A. 机も使ってハノイの塔の要領で入れる

上の図、見覚えがありませんか?そうです、ハノイの塔と酷似しています。ハノイの塔は棒が3本でしたので、カゴとカバンと机があれば完全にハノイの塔に落とし込めます。

まさかハノイの塔が日常生活で役に立つことがあるとは…

補足: 計算量について

ハノイの塔は荷物がN個あると 2N - 1 回移動させなければいけないので、一見すると非常に面倒に思えます。が、別にハノイの塔そのものではないので、律儀に1つずつ移す必要はありません。たとえば上から3つまとめて移動すればその分早くなります。まとめて移動すればN=3、ほとんどの場合はN=2のハノイの塔になるはずです。