15 min/d

ぼうずやのにっき

Cycle.js と Model-View-Indent をメモする

Cycle.js と Model-View-Intent

Cycle.js 。いろいろと悩み混乱しているのでここまでの理解をメモする。

Cycle.js では MVI (Model-View-Intent) という方針が示されている。これは公式のドキュメントに書かれている。

Intent の現状の理解は次のとおりだ。

Intent は drivers responses から actions をつくる。これは DOM Event や HTTP レスポンスなど drivers からの生の response からユーザーの意図している action に変換する。

たとえば、back button を click するのはユーザーの意図としては back という action をしたい、ということ。コードで表現すると次のようになる。

function intent(responses) {
  const { DOM } = responses;
  const actions = {
    back: DOM.select('button.back').events('click')
  };
  return actions;
}

responses は { DOM, HTTP } のような形式で、これは Cycle.run(main, drivers) の drivers に driver を登録した際のキーに対応している。

Model の現状の理解は次のとおりだ。

Model は状態を管理する。Intent から actions を受け取り state$ を返す。短い……。

例はこんな感じ。

import { Rx } from '@cycle/core';

function weight(actions) {
  return actions
    .changeWeight
    .startWith(70)
    .map(weight => ({ weight }));
}

function model(actions) {
  const state$ = Rx.Observable.combineLatest(
    weight(actions),
    (...args) => Object.assign(...args)
  );
  return state$;
}

正直なところ、かなり迷っている。

(...args) => Object.assign(...args) でまとめるために .map(weight => ({ weight })) のように各 props 側にまとめる処理をいれているところとか。

Observable.combineLatest で状態を { ... } という state に整形してから流すようにしているけど HTTP driver のように必要なときにしか値を流すべきでないもの (null{} を受け取ると死ぬ) に値を流さないようにするのが view の役割でいいのか……とか。

View の現状の理解は次のとおりだ。

View は state$ から driver requests をつくる。driver requests ってのが driver によってまちまちだけど DOM driver なら vtree$ だし HTTP driver なら request$ 。

これを一本の state$ から切り分けるの大丈夫なのかって感じではある。

import { h } from '@cycle/dom';

function DOM(state$) {
  return state$.map(({ weight }) => {
    return h('div', [
      'Weight: ' + weight + 'kg'
    ]);
  });
}

function HTTP(state$) {
  return state$
    .filter(({ request }) => request) // for null
    .map(({ request }) => request);
}

function view(state$) {
  return {
    DOM: DOM(state$),
    HTTP: HTTP(state$)
  }
}

HTTP driver を使う際の Model-View の切り分けや状態が謎。

Model や Intent では {...args} のために { prop }{ action } で返させていたのにここでは { driver } じゃないのも謎。

いろいろ模索している、ということで。