概要
Redux 上で Relay 的な実装ができる Adrenaline について調べました。
動機
React で GraphQL を使う場合、Relay を使うのが一般的です。
しかし、新規のプロジェクトでいきなり GraphQL というのはリスクがあるので、まずは Redux + REST で作っておき、少しずつ(例えば1画面ずつ) Relay + GraphQL に置き換えていければ、GraphQL を試すのには良いと考えました。
残念ながら、Relay も Redux も state を自分で管理しているため、外部から state を変更されると期待通りに動作せず、Relay と Redux を組み合わせることはできません。(参考)
そこで、Redux で Relay と同じような記法で書ける Adrenaline について調べました。
今回は adrenaline/example に少し修正を入れた sample_js_adrenaline を使って説明します。
Root
まず Root に <Adrenaline>
を追加します。
ReactDOM.render(
<Adrenaline schema={schema} renderLoading={Loader} createStore={createStore} >
{() => <Router history={history} children={routes} />}
</Adrenaline>,
rootNode
);
追加の middleware がない場合は、createStore={createStore}
を省略できます。
Smart and Dumb component
Adrenaline では Redux の Smart and Dumb component の考え方に基づいて、 Smart component で query や mutation を記述し、Dumb component に fragment を記述するようになっています。
Relay.createContainer
の代わりに、それぞれ createSmartComponent
/ createDumbComponent
を使って記述します。
class TodoApp extends Component {
:
}
export default createSmartComponent(TodoApp, {
initialArgs: {
count: 2,
},
query: `
query TodoApp($count: Int) {
viewer {
id,
${TodoList.getFragment('todos')}
}
}
`,
mutations: {
...todoMutations,
},
});
class TodoItem extends Component {
:
}
export default createDumbComponent(TodoItem, {
fragments: {
todo: `
Todo {
text
}
`,
},
});
以上のような記述で、Action の発行、GraphQL への fetch、props への反映をすべて Adrenaline が行ってくれます。
mutation も this.props.mutations.createTodo({text: "buy apple"})
のように ActionCreator と同じように使えます。
問題点
Redux + REST のプロジェクトから GraphQL への段階的な移行が目的でしたが、まだ次のような問題があります。
- GraphQL しか書けない。
- Reducer が追加できない。
今のままでは、Reducer が追加できないため、REST 通信などができなくなります。
これらについては、こちらのプルリク の Adapter で解決されます。
最後に
Adapter を拡張したプルリクの Adrenaline は実用的なレベルだと思います。
時間ができたら Relay で同じ実装をして比べてみようかと思います。