iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 21
0
Data Technology

GraphQL + ApolloData 入門系列 第 21

ApolloData & TypeScript (一)

介紹

Typescript 具有強行別的功能,強型別的好處就是可以有推導,智能提示,重構時候也會有參考可以看哪些沒有改到是一種開發階段就會把一些錯誤處理掉,不會帶到編譯時候再來處理會節省很多Debug的時間,另外Typescript也把 babel next的部分都整合進來,可以直接用最新的功能。

TypeScript的基礎設定

安裝 typescript

npm i typescript

跟目錄下設定 tsconfig.ts 使用方法與基本設定可以參考

https://ithelp.ithome.com.tw/articles/10191127

Operation result

ApolloData 有一個 Typescript 直接 Query 回傳結果的範例 ,直接看一下程式碼


import React from "react";
import gql from "graphql-tag";
import { graphql } from "react-apollo";

const HERO_QUERY = gql`
  query GetCharacter($episode: Episode!) {
    hero(episode: $episode) {
      name
      id
      friends {
        name
        id
        appearsIn
      }
    }
  }
`;

type Hero = {
  name: string;
  id: string;
  appearsIn: string[];
  friends: Hero[];
};

type Response = {
  hero: Hero;
};

const withCharacter = graphql<Response>(HERO_QUERY, {
  options: () => ({
    variables: { episode: "JEDI" }
  })
});

export default withCharacter(({ data: { loading, hero, error } }) => {
  if (loading) return <div>Loading</div>;
  if (error) return <h1>ERROR</h1>;
  return ...// actual component with data;
});

可以看到 < Response > 就是graphql的型別

const withCharacter = graphql<Response>(HERO_QUERY, {
  options: () => ({
    variables: { episode: "JEDI" }
  })
});

type Response 裡面 hero type 是 Hero
Hero 裡面的 appearsIn 是陣列裡面是 string 形態而 friends 的形態也是Type Hero

type Hero = {
  name: string;
  id: string;
  appearsIn: string[];
  friends: Hero[];
};

type Response = {
  hero: Hero;
};

Options

如果要給查詢一個條件式的時候,以下範例定義了 < Response, InputProps > 比上方直接回傳結果多一個InputProps

import React from "react";
import gql from "graphql-tag";
import { graphql } from "react-apollo";

const HERO_QUERY = gql`
  query GetCharacter($episode: Episode!) {
    hero(episode: $episode) {
      name
      id
      friends {
        name
        id
        appearsIn
      }
    }
  }
`;

type Hero = {
  name: string;
  id: string;
  appearsIn: string[];
  friends: Hero[];
};

type Response = {
  hero: Hero;
};

type InputProps = {
  episode: string
};

const withCharacter = graphql<Response, InputProps>(HERO_QUERY, {
  options: ({ episode }) => ({
    variables: { episode }
  }),
});

export default withCharacter(({ data: { loading, hero, error } }) => {
  if (loading) return <div>Loading</div>;
  if (error) return <h1>ERROR</h1>;
  return ...// actual component with data;
});

以上的 InputProps 定義為 episode: string 這邊是因為內部的 options會用到 props裡面有episode的型別參數


type InputProps = {
  episode: string
};

Props

因為ApolloData 是使用 High Order Component (Hoc)的方法讓props多一些功能,

import React from "react";
import gql from "graphql-tag";
import { graphql, NamedProps, QueryProps} from "react-apollo";

const HERO_QUERY = gql`
  query GetCharacter($episode: Episode!) {
    hero(episode: $episode) {
      name
      id
      friends {
        name
        id
        appearsIn
      }
    }
  }
`;

type Hero = {
  name: string;
  id: string;
  appearsIn: string[];
  friends: Hero[];
};

type Response = {
  hero: Hero;
};

type WrappedProps = Response & QueryProps;

type InputProps = {
  episode: string
};

const withCharacter = graphql<Response, InputProps, WrappedProps>(HERO_QUERY, {
  options: ({ episode }) => ({
    variables: { episode }
  }),
  props: ({ data }) => ({ ...data })
});

export default withCharacter(({ loading, hero, error }) => {
  if (loading) return <div>Loading</div>;
  if (error) return <h1>ERROR</h1>;
  return ...// actual component with data;
});

以上可以看到 props: ({ data }) => ({ ...data }) 這一段 這裡面的是屬於
graphql< Response, InputProps, WrappedProps > 第三個WrappedProps的型別,然後這個地方使用了組合的type方法 因為 ApolloData本身的Hoc就有添加一些好用的的props,所以這邊
import { graphql, NamedProps, QueryProps} from "react-apollo";
把原本回回傳的 Response 加上 QueryProps 定義成 props會回傳的形態

type WrappedProps = Response & QueryProps;

Classes vs Functions

除了定義玩 graphql Hoc的部分之外 被綁定的React Component 也需要做點設定 ,使用 react-apollo 的ChildProps 再給他型別 InputProps, Response

import { ChildProps } from "react-apollo";

class Character extends React.Component< ChildProps<InputProps, Response>, {} > 

import { ChildProps } from "react-apollo";

const withCharacter = graphql<Response, InputProps>(HERO_QUERY, {
  options: ({ episode }) => ({
    variables: { episode }
  })
});

class Character extends React.Component<ChildProps<InputProps, Response>, {}> {
  render(){
    const { loading, hero, error } = this.props.data;
    if (loading) return <div>Loading</div>;
    if (error) return <h1>ERROR</h1>;
    return ...// actual component with data;
  }
}

export default withCharacter(Character);

總結

Typesciprt 是一個很棒的語言,在開發上速度會快很多減少Debug的時間,雖然型別設定上比較繁雜,但是一但開始用後,就回不去了啊。

ApolloData 官方文件參考

https://www.apollographql.com/docs/react/features/static-typing.html

TypeScript 官方文件參考

https://www.typescriptlang.org/


上一篇
ApolloData & Upload套件 ClientPart
下一篇
ApolloData & TypeScript (二)
系列文
GraphQL + ApolloData 入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言