摘要:分鐘學(xué)是一個系列,簡單暴力,包學(xué)包會。接管了請求和狀態(tài)管理。一般在生產(chǎn)環(huán)境中,我們通常還希望做權(quán)限驗證請求攔截等事務(wù)處理。
21 分鐘學(xué) apollo-client 是一個系列,簡單暴力,包學(xué)包會。
搭建 Apollo client 端,集成 redux
使用 apollo-client 來獲取數(shù)據(jù)
修改本地的 apollo store 數(shù)據(jù)
提供定制方案請求攔截
封裝修改 client 的 api
apollo store 存儲細(xì)節(jié)寫入 store 的失敗原因分析和解決方案
我們已經(jīng)搭建了最小化的 ApolloClient。
Apollo 接管了 api 請求和狀態(tài)管理。一般在生產(chǎn)環(huán)境中,我們通常還希望做權(quán)限驗證、請求攔截等事務(wù)處理。
于是,我們就需要通過 Apollo 提供的一些接口,結(jié)合自己的業(yè)務(wù)需求,定制自己的 Apollo。
網(wǎng)絡(luò)層GraphQL 入門: Apollo Client - 網(wǎng)絡(luò)層
上面這篇文章中,介紹了 Apollo 網(wǎng)絡(luò)層的基礎(chǔ)知識,推薦閱讀。我只是再做一些補充。
fetchApollo 使用的是 fetch api
從源碼來看,apollo 代碼中并沒有包含 polyfill,也就是說,在低版本的瀏覽器上可能會因為缺少 fetch 而失敗。所以你需要安裝 isomorphic-fetch
另外,如果你碰到跨域等問題,也是 fetch 引起的,和 apollo 沒什么關(guān)系。
const networkInterface = (createNetworkInterface({ uri: "...", opts: { // fetch 相關(guān)的設(shè)置在這里配置 credentials: "same-origin", }, }));network middlewares
如果你使用過 Express 的話,就能很容易理解這個概念。否則你也可以理解為 middleware 就是請求的攔截器,可以在每個請求發(fā)送前或發(fā)送后,攔截請求,對其做一些修改,再決定是否傳遞,也可以直接取消。
所以你可以在這里
設(shè)置 headers
權(quán)限驗證
取消請求
緩存請求
實踐中,建議把所有的 middlewares 寫到一個多帶帶的文件。
我個人比較喜歡寫簡化的代碼,你也可以參考我進行配置。
middlewares.js
const wrapMiddlewares = (key) => (mws) => mws.map(mw => ({ [key]: mw })); const wrapBeforewares = wrapMiddlewares("applyMiddleware"); const wrapAfterwares = wrapMiddlewares("applyAfterware"); // 可以看成一個沒有冗余代碼的配置表 export default function applyApolloMiddlewares(networkInterface) { networkInterface.use(wrapBeforewares([ setHeaders, ])) .useAfter(wrapAfterwares([ checkAuth, ])); return networkInterface; } // ---- 請求前 ---- function setHeaders(req, next) { try { if (!req.options.headers) { req.options.headers = { "Content-Type": "application/json;charset=utf-8", }; } } catch (e) { console.error(e); } // 必須返回 next next(); } // ---- 請求后 ----- function checkAuth({ response: res }, next) { try { // 自行處理 401 等各種 statusCode } catch (e) { console.error(e); } next(); }
建議對所有的 middlewares 包裹一層 try catch,因為我發(fā)現(xiàn) apollo 這個庫不能很好地報錯,經(jīng)常靜默失敗。
于是你的 createApolloClient 函數(shù)可以改寫為
createApolloClient.js
import { ApolloClient, createNetworkInterface } from "react-apollo"; import applyApolloMiddlewares from "./middlewares"; const networkInterface = (createNetworkInterface({ uri: "...", opts: { // fetch 相關(guān)的設(shè)置在這里配置 credentials: "same-origin", }, })); const client = new ApolloClient({ networkInterface: applyApolloMiddlewares(networkInterface), }); return client;FragmentMatcher
正式請求中,如果你的 schema 包含了 union type,形如
content { # 類型為 Content ... on Article { id title } ... on Timeline { id content } }
即根據(jù)返回數(shù)據(jù)的類型不同,抓取不同的數(shù)據(jù),這在 GraphQL 中,使用的是 inline fragment 語法來解決。
而上面代碼中的 Content 這個類,本身沒有具體字段,但有許多子類,被稱為 union type。
可以看看 GraphQL 關(guān)于這一細(xì)節(jié)的描述:inline-fragments。
apollo 中使用一種啟發(fā)式的類型搜索方式,不像后端已經(jīng)存在所有的類型說明,前端為了類型安全,必須由你來告訴 apollo,該 union type 下到底有哪些子類
否則你可能會看到這樣的報錯
You are using the simple (heuristic) fragment matcher, but your queries contain union or interface types. Apollo Client will not be able to able to accurately map fragments
報錯信息會指引你閱讀這個文檔,說的就是我上面描述的情況:Using Fragments on unions and interfaces
為了少寫垃圾代碼,我寫了一些 helper,希望對你有用。
const createIntrospectionFactory = (kind) => (name, possibleTypes) => ({ name, kind, possibleTypes: possibleTypes.map(typename => ({ name: typename })), }); const createInterface = createIntrospectionFactory("INTERFACE"); const createUnion = createIntrospectionFactory("UNION"); export default { introspectionQueryResultData: { __schema: { types: [ createInterface("Content", [ "Article", "Timeline", ]), ] } } };
所以你的 client 可以寫成
import { ApolloClient, createNetworkInterface, IntrospectionFragmentMatcher } from "react-apollo"; import applyApolloMiddlewares from "./middlewares"; import fragmentMatcher from "./fragmentMatcher"; export default function createApolloClient() { const networkInterface = (createNetworkInterface({ uri: "...", opts: { credentials: "same-origin", }, })); const client = new ApolloClient({ networkInterface: applyApolloMiddlewares(networkInterface), fragmentMatcher: new IntrospectionFragmentMatcher(fragmentMatcher), }); return client; }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/91923.html
摘要:分鐘學(xué)是一個系列,簡單暴力,包學(xué)包會。那怎么辦呢本章就教你非常簡單地實現(xiàn)擴展的。我們可以借鑒的的寫法,為的實例添加一些自己的方法。更重要的是,也會有的效果,上一個的輸出會成為下一個的輸入,便于組合。 21 分鐘學(xué) apollo-client 是一個系列,簡單暴力,包學(xué)包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)修改本地的 ...
摘要:分鐘學(xué)是一個系列,簡單暴力,包學(xué)包會。內(nèi)部通過自己的私有沒有暴露給開發(fā)者來更新這個。相當(dāng)于這個就是自己維護的,它將所有通過得到的數(shù)據(jù)保存在這里。的生成規(guī)則根據(jù)官方文檔的說法,在創(chuàng)建時,可選設(shè)置。如果不存在,則可能出現(xiàn)。 21 分鐘學(xué) apollo-client 是一個系列,簡單暴力,包學(xué)包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來...
摘要:分鐘學(xué)是一個系列,簡單暴力,包學(xué)包會。其中提到了等需要后端配合的東西,徒增了配置的復(fù)雜性。如果不行,再跟隨我的簡單步驟試試。環(huán)境要求請確保你已經(jīng)搭建了自己的環(huán)境下文在行號前添加表示刪除的原代碼,表示新增的代碼。 21 分鐘學(xué) apollo-client 是一個系列,簡單暴力,包學(xué)包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)...
摘要:分鐘學(xué)是一個系列,簡單暴力,包學(xué)包會。一旦你丟失了,可能會導(dǎo)致寫入失敗,或者盡管寫入了,但本該攜帶的那一層的數(shù)據(jù)沒有寫入。 21 分鐘學(xué) apollo-client 是一個系列,簡單暴力,包學(xué)包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)修改本地的 apollo store 數(shù)據(jù)提供定制方案 請求攔截 封裝修改 clie...
摘要:分鐘學(xué)是一個系列,簡單暴力,包學(xué)包會。一旦組件掛載后,會自動進行數(shù)據(jù)請求,前提是客戶端提供的和后端的相符。如果回調(diào)返回直接不作請求。在組件內(nèi)進行分頁請求之前提到了,這個裝飾器為添加了對象,其中有個函數(shù)為。 21 分鐘學(xué) apollo-client 是一個系列,簡單暴力,包學(xué)包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)修改本...
閱讀 3163·2021-09-30 09:47
閱讀 2022·2021-09-22 16:04
閱讀 2290·2021-09-22 15:44
閱讀 2550·2021-08-25 09:38
閱讀 550·2019-08-26 13:23
閱讀 1238·2019-08-26 12:20
閱讀 2819·2019-08-26 11:59
閱讀 1087·2019-08-23 18:40