全棧 React + GraphQL 教程(一)

首發於衆成翻譯javascript


Part 1——前端:使用 Apollo 聲明式地請求和 mock 數據

GraphQL 是一種新的 API 定義和查詢語言,有可能成爲新的 REST。它使 UI 組件易於聲明式地獲取數據,而沒必要關注後端實現細節。GraphQL 做爲一種強大的抽象,能夠加快應用開發速度,使代碼更容易維護。css

然而,儘管使用 GraphQL 有諸多好處,但邁出第一步可能並不容易。這就是爲何我編寫了這一系列教程,帶你一步步地編寫一個包含 GraphQL 和 Apollo Client 的全棧 React 應用。該系列將引導你完整構建一個使用 GraphQL 的即時消息應用:html

本教程——做爲這一系列中的第一篇——是關於如何在前端開始使用 GraphQL。只須要大約20-30分鐘,最終你會獲得一個很是簡單的 React UI,它使用 GraphQL 加載數據,看起來像這樣:前端

一個使用 GraphQL 加載數據的簡易 React UIjava

讓咱們開始吧!node

1. 環境搭建

注意:要完成此教程,你須要在你的機器上安裝 node,npm 和 git,而且對 React 有所瞭解。react

咱們將在本教程中使用 create-react-app,因此執行安裝:git

> npm install -g create-react-app

咱們還須要從 GitHub 中克隆本教程的代碼庫,其中包含了咱們稍後會使用到的 CSS 和圖像。github

> git clone https://github.com/apollographql/graphql-tutorial.git
> cd graphql-tutorial

接下來,咱們使用 create-react-app 建立咱們的 react 應用。npm

> create-react-app client
> cd client

爲了確保它能工做,咱們啓動服務器:

> npm start

若是一切正常,你如今應該在瀏覽器中看到以下內容:

2. 編寫第一個組件

因爲咱們正在使用 Apollo 構建一個應用,因此咱們經過從 ../ resources 複製 logo.svgApp.css 來修改 logo 和 CSS。

> cd src
> cp ../../resources/* .

爲了簡化初始教程,咱們今天只構建一個簡單的列表視圖。讓咱們修改 App.js 中的代碼:

  1. 修改 「Welcome to React」 爲 「Welcome to Apollo」。Apollo 是咱們將在本教程系列中使用的 GraphQL 客戶端的名稱。
  2. 刪除 「To get started ..」段落,並用純 React 組件替換它,該組件將渲染一個具備兩個列表項的無序列表,「Channel 1」和 「Channel 2」(是的,你猜到了,咱們要構建一個通訊應用!)。咱們將列表組件命名爲 ChannelsList

如今你的 App.js 應該以下所示:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
const ChannelsList = () =>
     (<ul>
       <li>Channel 1</li>
       <li>Channel 2</li>
     </ul>);
class App extends Component {
   render() {
     return (
       <div className="App">
         <div className="App-header">
           <img src={logo} className="App-logo" alt="logo" />
           <h2>Welcome to Apollo</h2>
         </div>
         <ChannelsList />
       </div>
     );
   }
 }
export default App;

create-react-app 爲你設置好了熱加載,因此一旦你保存文件,你的應用所在的瀏覽器窗口將會更新以反映更改:

若是看起來像這樣,你的設置就是正確的。

3. 編寫你的 GraphQL schema

如今咱們有一個簡單的應用正在運行,如今是爲它編寫 GraphQL 類型定義的時候了。 Schema 將指定咱們的應用中存在哪些對象類型,以及它們有哪些字段。此外,它指定了咱們的 API 的入口。咱們新建一個名爲 schema.js 的文件:

export const typeDefs = `
type Channel {
   id: ID!                # "!" 爲必填
   name: String
}
# 此類型指定了咱們的 API 的入口點。在本例中,只有一個——"channels"——返回頻道列表。
type Query {
   channels: [Channel]    # "[]" 意味着這是頻道列表
}
`;

有了這個 schema,咱們能夠在下節中編寫一個簡單的查詢來獲取咱們的 ChannelList 組件的數據。這是咱們的查詢:

query ChannelsListQuery {
  channels {
    id
    name
  }
}

4. 將你的組件鏈接 GraphQL 查詢

好,如今咱們有了 schema 和查詢,咱們只須要使用 Apollo Client 鏈接咱們的組件!咱們來安裝 Apollo Client 和一些輔助軟件包,咱們須要將 GraphQL 添加到咱們的應用中:

> npm i -S react-apollo

react-apollo 是 Apollo Client 與 React 的整合,可讓你使用名爲 graphql高階組件來裝飾組件,它將你的 GraphQL 數據不費力地導入到組件中。React Apollo 還提供了 ApolloClient,它是 Apollo 的核心,處理全部數據獲取,緩存和積極更新(咱們將在另外一個教程中討論)。

如今,咱們在 App.js 的頂部添加一些導入,並建立一個 Apollo Client 的實例:

import {
  ApolloClient,
  gql,
  graphql,
  ApolloProvider,
} from 'react-apollo';
const client = new ApolloClient();

接下來,咱們使用 GraphQL 高階組件來裝飾原來的 ChannelsList,該高階組件接受查詢並將數據傳遞給咱們的組件:

const channelsListQuery = gql`
   query ChannelsListQuery {
     channels {
       id
       name
     }
   }
 `;
const ChannelsListWithData = graphql(channelsListQuery)(ChannelsList);

當咱們的 ChannelsList 組件使用 graphql HOC 包裝時,將會收到一個名爲 data 的 prop,當它可用時會包含 channel,當有錯誤時會顯示 error。另外 data 還包含一個 loading 屬性,當 Apollo Client 在等待數據獲取的時候它的值爲 true

接下來修改咱們的 ChannelsList 組件,以確保用戶知道該組件是否正在加載,或者是否出現錯誤:

const ChannelsList = ({ data: {loading, error, channels }}) => {
   if (loading) {
     return <p>Loading ...</p>;
   }
   if (error) {
     return <p>{error.message}</p>;
   }
return <ul>
     { channels.map( ch => <li key={ch.id}>{ch.name}</li> ) }
   </ul>;
 };

最後,咱們用 ChannelsListWithData 替換 App 的 render 函數中的 ChannelsList。 爲了讓咱們剛建立的組件可以使用 Apollo Client 的實例,咱們用 ApolloProvider 包裹頂級的應用組件,這會將 Apollo Client 的一個實例放在 UI 上。

如今你的 App 組件應該以下所示:

class App extends Component {
   render() {
     return (
       <ApolloProvider client={client}>
         <div className="App">
           <div className="App-header">
             <img src={logo} className="App-logo" alt="logo" />
             <h2>Welcome to Apollo</h2>
           </div>
           <ChannelsListWithData />
         </div>
       </ApolloProvider>
     );
   }
 }

好的,咱們快完成了!若是你如今嘗試運行,應該會看到如下錯誤:

起做用了!——好吧,至少部分如此。

這是怎麼回事?儘管咱們正確地鏈接了全部的組件,但咱們尚未寫一個服務器,因此固然沒有數據能夠獲取或顯示! 若是你沒有爲 GraphQL 端點指定 URL,Apollo Client 將假定它運行在同一個域下的 /graphql。所以咱們須要建立一個具備自定義 URL 的網絡接口。

可是,因爲本教程不是關於編寫服務器的,因此咱們將利用 GraphQL 代碼即文檔這一特性,根據咱們先前寫過的類型定義自動建立 mock。要實現這一點,咱們只須要中止服務器,安裝一些其餘的軟件包,而後從新啓動它:

npm i -S graphql-tools apollo-test-utils graphql

咱們將使用這些軟件包根據咱們前面寫的 schema 爲 Apollo Client 建立一個模擬網絡接口。將如下導入和定義添加到 App.js 的頂部:

import { 
  makeExecutableSchema,
  addMockFunctionsToSchema
} from 'graphql-tools';
 import { mockNetworkInterfaceWithSchema } from 'apollo-test-utils';
 import { typeDefs } from './schema';
const schema = makeExecutableSchema({ typeDefs });
addMockFunctionsToSchema({ schema });
const mockNetworkInterface = mockNetworkInterfaceWithSchema({ schema });

如今你只需將 mockNetworkInterface 傳遞給 Apollo Client 的構造函數:

const client = new ApolloClient({
   networkInterface: mockNetworkInterface,
 });

就是這樣,你已經完成了!你的屏幕如今應該以下所示:

咱們作到了,咱們的第一個使用 Apollo 的 React + GraphQL 應用!

注意:「Hello World」 只是字符串的默認模擬文本。 若是你想自定義酷炫的 mock,請查看我以前寫的這篇文章

若是某些代碼不起做用,而且你搞不清是爲何,你能夠將其與此文件進行比較,以發現代碼差別。或者,你能夠查看 t1-end Git 分支來檢查代碼。


恭喜,你已經正式完成了教程的第一部分!可能沒什麼感受,但實際上已經作了不少工做:你已經編寫了一個 GraphQL schema,從中生成模擬數據,並將 GraphQL 查詢與 React 組件相連。在本教程的其他部分中,你將瞭解到咱們構建一個真正的通訊應用的基礎。在第2部分中,咱們將編寫一個簡單的服務器並將其鏈接到咱們的應用!

相關文章
相關標籤/搜索