仿Trello - 前端 Apollo Client 串接 GraphQL API

本系列文以制作专案为主轴,纪录小弟学习React以及GrahQL的过程。主要是记下重点步骤以及我觉得需要记忆的部分,有觉得不明确的地方还请留言多多指教。

後端API建立好了,现在回到前端来发送请求取得资料。

Apollo 针对前端也有工具,Apollo client,可以在发送GraphQL请求後建立前端cache,在前端发送重复请求时直接从快取存取资料,降低向Server请求的频率。

这个Cache其实就如同Redux的Store,所以除了向Server请求资料外,Apollo Client也能用於前端状态管理,好处在於可以用GraphQL的方式存取local state,灵活性高。

目前的 Apollo 版本没有跟Redux的store集成的方法,只能各管各的,或是直接取代Redux 用 Apollo 做 local state的管理,不过这边只是学习笔记,就不弄大工程取代掉Redux,简单示范如何用 Apollo Client 进行 GraphQL 请求。

安装

回到 client资料夹,用 npm 安装套件:

npm install @apollo/client graphql

在 index.js 中建立 Apollo client 实例:

//index.js
//...
import { ApolloClient, InMemoryCache } from "@apollo/client";

const client = new ApolloClient({
  uri: "http://localhost:4000/",  //指定API网址
  cache: new InMemoryCache(), //建立 cache
});
//...

然後将 client 应用给 APP:

//index.js
//...
import {  ApolloProvider } from "@apollo/client";

//...

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client}>  //将APP包装
      <Provider store={store}>   //这是原本的Redux Store
        <App />
      </Provider>
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

这样发送 GraphQL 请求的准备就完成了。

useQuery

Apollo Client 在2.6版後改以 hook 的方式进行 query 跟 mutation。而要进行请求,要先撰写graphQL 请求字串,在提供给hook 使用。

以query lists为例,先将 useQuery 跟 gql 标签引入KanBan:

//KanBan.jsx
import { useQuery, gql } from "@apollo/client";

const GET_LISTS = gql`
  query GetLists {
    lists {
      id
      title
      todos {
        id
        name
      }
    }
  }
`;

注意必须要以 gql 标签将字串转为请求物件。

接着就能在元件中以 useQuery 发送请求取得资料

//KanBan.jsx
export default function KanBan({ lists, editState, kanBanMenuState }) {
  const { loading, error, data } = useQuery(GET_LISTS);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :(</p>;
  console.log(data.lists);

  //...
}

useQuery的回传值中有一些请求的进行状态,像是loading为true时表示请求还在处理中,就可以利用这个布林值先渲染载入画面。

而当请求完成後就能从data取得资料用於元件渲染,或是error取得错误讯息。

useMutation

跟 useQuery 一样可以用 useMutation 进行 mutation 请求,顺便示范如何在请求中带入参数。

一样先引入 fucntion 後用 gql 编写请求:

//List.jsx
import { gql, useMutation } from "@apollo/client";

const ADD_TODO = gql`
  mutation AddTodo($name: String!, $listId: Int!) {
    addTodo(name: $name, listId: $listId) {
      id
      name
    }
  }
`;

注意宣告 AddTodo 时宣告了参数与其型别,然後其中的请求时再以这些参数带入请求。

将ADD_TODO用於 mutation:

const List = React.forwardRef(...)=> {

const [addTodo] = useMutation(ADD_TODO);

//...
}

useMutation 回传值第一个是执行请求的function,可以在click时呼叫:

//NewTodo.jsx

//...

function handleAddTodo(e) {
if (e.target.value.trim()) {
  addTodo({ variables: { listId: listId, name: e.target.value } });
}

e.target.value = "";
toggleShowNew();
}
//...

要提供物件作为参数给addTodo,并以 variables 宣告带入请求的参数。

成功执行 mutation 後应该会发现页面并没有相应的变化,因为 mutatoin 修改完 Server、资料库的讯息後本地端的cache并不一定会自动更新,可以重新发送query请求不过那太耗资源了,应该要在mutation後利用回传的讯息编辑cache。

编辑 cache 还挺复杂的,就分篇吧。

References:


<<:  Day 26 讨论 AI 深度学习论点

>>:  Day 26 - 部署 NestJS 到 AWS Elastic Beanstalk (1)

饭店的奇闻轶事

今天心情郁闷只好来写一些特别的东西,来跟大家聊聊空服的外站人生。 还记得那是一个很冷很冷的冬天,历经...

【Day25】 Transformer 实作包(二)

开始施工 今天我们要来制作 Transformer Decoder 的部分,一样先上个图方便施工 以...

2.4.11 Design System - Switches/Toggle

作息的重要性 我大部分的时候可以属於夜猫子类型 但几次实验下来发现 熬夜→睡不饱→上班想睡→花比较...

★ 2021 IPBC Taiwan|创新科技论坛-智胜5G 领航未来! ★ 经济部工业局 主办 !

★2021 IPBC Taiwan|创新科技论坛-智胜5G 领航未来!★ 经济部工业局 主办! ht...

DAY 1 - 蜥蜴拳修士

灯灯灯~ 好不容易挤出来啊~ 差点难产! 那就让我们开始乱涂吧~ 喔耶~ <( ̄︶ ̄)/ 目标...