Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
GraphqlとReact
Search
Taketoshi Aono(青野健利 a.k.a brn)
June 07, 2017
Programming
120
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GraphqlとReact
GraphqlとReactを組み合わせた場合のフレームワークの良し悪しとか紹介とか
Taketoshi Aono(青野健利 a.k.a brn)
June 07, 2017
More Decks by Taketoshi Aono(青野健利 a.k.a brn)
See All by Taketoshi Aono(青野健利 a.k.a brn)
document.write再考
brn
7
3.2k
Parsing Javascript
brn
14
9.6k
JSON & Object Tips
brn
1
600
CA 1Day Youth Bootcamp for Frontend LT
brn
0
1.1k
Modern TypeScript
brn
2
890
javascript - behind the scene
brn
3
820
tc39 proposals
brn
0
1k
プロダクト開発とTypeScript
brn
7
3k
React-Springでリッチなアニメーション
brn
1
780
Other Decks in Programming
See All in Programming
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
150
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
0
1.7k
What We Talk About When We Talk About XP
m_seki
2
670
iOSDC2026登壇資料.pdf
riofujimon
0
170
SONY CISC-NEWS NWS-1750 + NWB-225 フレームバッファの NetBSD/news68k ドライバ実装 / OSC2026Hiroshima
tsutsui
0
130
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
5
3.8k
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
2.2k
海上で動くGoサーバー: goroutineとchannelでさばく航行データストリーム
atsuki_seo
0
850
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
350
App Intentsのビルドプロセスを支える技術
kntkymt
0
410
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
460
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
640
Featured
See All Featured
Building the Perfect Custom Keyboard
takai
2
880
Heart Work Chapter 1 - Part 1
lfama
PRO
10
36k
Thoughts on Productivity
jonyablonski
76
5.4k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
330
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.1k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
990
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
700
Making the Leap to Tech Lead
cromwellryan
135
10k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
So, you think you're a good person
axbom
PRO
2
2.2k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
1
530
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
Transcript
Graphql with Reactjs
名前: @brn (青野健利) 職業: フロントエンドエンジニア・ネイティブエンジニア 会社: Cyberagent アドテクスタジオ RightSegment・AI Messenger
ブログ: http://abcdef.gets.b6n.ch/
Why graphql? フロントエンド主導でAPIの設計ができる。 より複雑化していくSPAの設計に向いている。
Why React? Viewを宣言的に書ける。 状態をViewから切り離すことができる。 これらをそこそこの速度で実現している。
React+Graphql Reactでgraphqlを使うなら、できるだけ親和性が高いライブラリを選びたい。
Relay Facebook製のライブラリで、Reactを組み合わせる前提で作られた。 Facebookでは実際に使用されている。
Relay インストール npm install react-relay --save
Relay import React from 'react'; import Relay from 'react-relay'; class
App extends React.Component { render() { return ( <ul> {this.props.todos.todos.edges.map(edge => <li key={edge.node.id}>{edge.node.name} (ID: {edge.node.id})</li>)} </ul> ); } } Component
Relay export default Relay.createContainer(App, { fragments: { todos: () =>
Relay.QL` fragment on Todos { todos(first: 1) { edges { node { id value }, }, }, } `, }, }); Container
Relay Relay Container Component React Component Server Parent Component Relay
Store Props Read Query Response Response
Relay import Relay from 'react-relay'; export default class extends Relay.Route
{ static queries = { viewer: () => Relay.QL` query { todos } `, }; static routeName = 'AppHomeRoute'; } Route
Relay import 'babel-polyfill'; import App from './components/App'; import AppHomeRoute from
'./routes/AppHomeRoute'; import React from 'react'; import ReactDOM from 'react-dom'; import Relay from 'react-relay'; ReactDOM.render( <Relay.Renderer environment={Relay.Store} Container={App} queryConfig={new AppHomeRoute()} />, document.getElementById('root') ); App
Relay これで完成!と言いたいところですが… RelayはBabelを前提に作られており、 Relay.QL`<query>` の部分はランタイムでは実行できません。 Babelによってコンパイルされることで関数になり、実行できるようになります。 なので、早速 npm install babel-relay-plugin
でインストールします。
Relay 今度こそ! Error : Invalid introspection data supplied to `getBabelRelayPlugin()`.
The resulting schema is not an object with a `__schema` property or a schema IDL language. while parsing file…
Relay どうやらSchema.jsonと言うものが必要なようなのですが、 作り方も何なのかもドキュメントがなく、ただ、 relay-starter-kitというgitリポジトリにあるとだけ書いてあります…
Relay
Relay schema.jsonの正体はGraphQLの型定義のメタデータで、 introspectionQueryという機能を利用し自動生成する。 relay-starter-kitのscriptsディレクトリに詳細があるので、そこをみるとよろし。 私はもうRelayはやめます!
Relay ここが駄目だよRelayちゃん とにかくAPIが複雑。すぐ使えるようなものではない上に Documentがexampleベースなのだが、そのexampleも複雑なので、 読む気がしない。 Babel前提なのはいいが、schema.json作れとか面倒すぎる。 Relay.Routeとか意味がわかりづらすぎ。 Reduxとも組み合わせづらい relay-modernである程度はよくなりそうだが…
React-apollo そこで、react-apolloです
React-apollo React-apolloとは React環境(React-native等)ならどこでも動くGraphQLクライアント ビルド設定等不要で、jsランタイムさえあれば動きます。 基本的にかなりシンプルで使いやすいです。
React-apollo インストール npm install react-apollo --save
React-apollo import { ApolloClient, createNetworkInterface } from 'react- apollo'; export
const client = new ApolloClient({ networkInterface: createNetworkInterface({ uri: 'http://localhost:3000/graphql' }) }); Client
React-apollo import { gql, graphql } from 'react-apollo'; import React
from 'react'; const QUERY = gql` query TodoAppQuery($id: ID) { todos(id: $id) { id text } }`; @graphql(QUERY, { options(props) { return {id: props.id} } }) export default class TodoApp extends React.Component { render() { const {fetchMore, refetch, todos = []} = this.props.data; return ( <div> <button onClick={() => refetch()}>Refresh</button> <ul>{todos.map(todo => <li key={todo.id}>{todo.text}</li>)}</ul> </div> ); } } Component
React-apollo import { ApolloProvider } from 'react-apollo'; import ReactDOM from
'react-dom'; import React from 'react'; import {client} from './client'; import TodoApp from './todo'; ReactDOM.render(( <ApolloProvider client={client}> <TodoApp id={null}/> </ApolloProvider> ), document.querySelector('#app')); App
React-apollo 後はBabel等でjsxをコンパイルすれば動きます。 特に面倒な設定は無いはず!
React-apollo Client Apolloがサーバにアクセスする際のエンドポイントを指定します。 ここにはMiddlewareも指定できて、リクエスト・レスポンスの編集も可能です。
React-apollo import ApolloClient, { createNetworkInterface } from 'apollo-client’; const networkInterface
= createNetworkInterface({ uri: '/graphql' }); networkInterface.use([{ applyMiddleware(req, next) { if (!req.options.headers) { req.options.headers = {}; // Create the header object if needed. } req.options.headers['authorization'] = localStorage.getItem('token') ? localStorage.getItem('token') : null; next(); } }]); const client = new ApolloClient({ networkInterface, }); App
React-apollo Component apolloでReactComponentをラップすることで、 GraphQLのリクエストを行える様にする。 ここはRelayと同じだが、Relayと違ってES Decoratorを利用する事ができるのと、 コンポーネント側に便利なPropsが提供されている。
React-apollo data: { loading: false, error: null, variables: { id:
'asdf' }, refetch() { ... }, fetchMore() { ... }, startPolling() { ... }, stopPolling() { ... }, // ... more methods } this.props.data配下に便利なメソッド、プロパティが定義される
React-apollo ApolloProvider 最後にApolloProviderでReactComponentTreeにGraphQLリクエスト機能を渡す。 ここで、ReduxのStoreと連携することも可能
React-apollo+Redux import { gql, graphql } from 'react-apollo'; import {connect}
from 'react-redux'; import React from 'react'; import {addTodo, getTodos} from './action'; @connect((state) => state, (dispatch) => ({ addTodo(todo) {return dispatch(addTodo(todo))}, getTodos(todo) {return dispatch(getTodos(todo))} })) @graphql(ADD_QUERY, { props({ownProps, mutate}) { return { addTodo(text) { mutate({variables: {text}}).then(t => ownProps.addTodo(t.data.addTodo)); } } } }) @graphql(QUERY, { options(props) { return {id: props.id}; }, skip: props => typeof window === 'object' }) export default class TodoApp extends React.Component { constructor(p, c) { super(p, c); } render() { const {todosRoot: {todos = []}, addTodo} = this.props; return ( <div> <div> <input type="text" onChange={e => this._handleInput(e)}/> <button onClick={() => addTodo(this._value)}>add</button> </div> <button onClick={() => this.props.apollo.refetch()}>Refresh</button> <ul>{todos.map(todo => <li key={todo.id}>{todo.text}</li>))}</ul> </div> ); } } Component
React-apollo+Redux import { createStore, combineReducers, applyMiddleware, compose } from 'redux’;
import {ApolloClient} from 'react-apollo'; import todoReducer from './reducer'; export default (client) => { return createStore( combineReducers({ todosRoot: todoReducer, apollo: client.reducer() }), typeof window === 'object'? window.__APOLLO_STATE__: {}, // initial state compose( applyMiddleware(client.middleware()), (typeof window === 'object' && typeof indow.__REDUX_DEVTOOLS_EXTENSION__ ! == 'undefined') ? window.__REDUX_DEVTOOLS_EXTENSION__() : f => f ) ); }; Store
React-apollo SSR React-apolloはServerSideRenderingにも対応していて、 簡単な設定でSSRできます!
React-apollo SSR import 'isomorphic-fetch'; import fs from 'fs'; import express
from 'express'; import ejs from 'ejs'; import React from 'react'; import TodoApp from '../client/src/todo.jsx'; import {client} from '../client/src/client'; import {renderToString} from 'react-dom/server'; import {ApolloProvider, getDataFromTree} from 'react-apollo'; const app = express(); const template = fs.readFileSync('./index.html', 'utf8'); const tree = <ApolloProvider client={client}><TodoApp id={1}/></ ApolloProvider>; app.get('/', (req, res) => { getDataFromTree(tree).then(v => { res.end(ejs.render(template, {dom: renderToString(tree)})); }); }); app.listen(3000);
React-apollo SSR SSRで重要な点 • isomorphic-fetchのインストール • getDataFromTreeで実際にリクエストを行う • 初期状態をhtml上にjsonで渡す。
React-apollo SSR まとめ react-apolloとnodejsでisomorphicなGraphQL生活を!