成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

21 分鐘學(xué) apollo-client 系列:獲取數(shù)據(jù)

robin / 3510人閱讀

摘要:分鐘學(xué)是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。一旦組件掛載后,會(huì)自動(dòng)進(jìn)行數(shù)據(jù)請(qǐng)求,前提是客戶端提供的和后端的相符。如果回調(diào)返回直接不作請(qǐng)求。在組件內(nèi)進(jìn)行分頁請(qǐng)求之前提到了,這個(gè)裝飾器為添加了對(duì)象,其中有個(gè)函數(shù)為。

21 分鐘學(xué) apollo-client 是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。

搭建 Apollo client 端,集成 redux
使用 apollo-client 來獲取數(shù)據(jù)
修改本地的 apollo store 數(shù)據(jù)
提供定制方案

請(qǐng)求攔截

封裝修改 client 的 api

apollo store 存儲(chǔ)細(xì)節(jié)
寫入 store 的失敗原因分析和解決方案

使用 Apollo 獲取數(shù)據(jù)

推薦先看:GraphQL 入門: 連接到數(shù)據(jù)
本文只做補(bǔ)充。

下面編寫一個(gè)最簡(jiǎn)單的 Container,觀察是否能 query 到數(shù)據(jù)。

container.jsx

import React, { PureComponent } from "react";
import { graphql } from "react-apollo";
import query from "./query.gql";

@graphql(query)
export default class ApolloContainer extends PureComponent {
    render() {
        console.log(this.props);
        return 
Hello Apollo
; } }

@graphql(query) 是 apollo 提供的高階組件,以裝飾器的形式包裹你的組件。這里是最簡(jiǎn)單的情況,只傳一個(gè) query。

query 語法

基本的 query 語法可以參看官方文檔 Queries and Mutations | GraphQL,這里提一下 Apollo 特有的一些語法。

query.gql

#import "../gql/pageInfo.gql"
#import "@/gql/topic/userTopicEntity.gql"

query topic($topicId: Int!, $pageNum: Int = 1) {
    community {
        topicEntity {
            listByTopicId(topicId: $topicId, pageSize: 10, pageNum: $pageNum) {
                pageInfo {
                    ...pageInfo
                }
                edges {
                    ...userTopicEntity
                }
            }
        }
    }
}

前兩行 import 了其它的 fragment。想必你已經(jīng)知道,GraphQL 主要通過 fragment 來組合分形 Query。一個(gè)好的實(shí)踐是盡量對(duì)業(yè)務(wù)實(shí)體編寫 fragment 以便復(fù)用。
代碼脫敏的關(guān)系我就不放詳細(xì)的 fragment 了。

上一節(jié)我們?cè)?webpack 中配置了 graphql-tag/loader,這個(gè) loader 允許你將 query 、fragment 這些 schema 字符串,以 .gql 文件的形式保存,在 import 時(shí)轉(zhuǎn)化成 js 代碼。

其余部分,基本上和 GraphQL 原生寫法是一樣的,注意幾個(gè)點(diǎn):

一次請(qǐng)求只能包含一個(gè) query,而且不能包含未使用的 fragment。

#import 語法是 loader 提供的,語法和 js 的 import 差不多,除了不能解構(gòu) 。
如果你 webpack 配置了 alias 就能使用第二行那種寫法。注意,它會(huì)把該文件內(nèi)所有的內(nèi)容都 import 進(jìn)來,所以不能在一個(gè) gql 文件里寫多個(gè) queryfragment

對(duì)了,為了最小化實(shí)踐,你可以先寫不帶參數(shù)的 query。也先不要寫 union type。

props.data 的數(shù)據(jù)結(jié)構(gòu)

這樣就好了嗎,是的。一旦組件掛載后,會(huì)自動(dòng)進(jìn)行數(shù)據(jù)請(qǐng)求,前提是客戶端提供的 query schema 和后端的相符。

如果請(qǐng)求成功后,會(huì)發(fā)生什么事情呢?我們可以查看 this.props 打出的 log 來驗(yàn)證:

// this.props
{
    // ....
    data: {
        // ...
        community: { ... }, // 這是獲取到的數(shù)據(jù),結(jié)構(gòu)和你提供的 query schema 一致
        loading: false, // 請(qǐng)求過程中為 true
        networkStatus: 7, // 從 0-8,具體值的含義看這個(gè)文件 https://github.com/apollographql/apollo-client/blob/master/src/queries/networkStatus.ts
        variables: { ... }, // 請(qǐng)求時(shí)所用的參數(shù)
        fetchMore, // 一個(gè)函數(shù),用于在組件內(nèi)「繼續(xù)請(qǐng)求」,一般用于分頁請(qǐng)求
        refetch, // 函數(shù),用于組件內(nèi)「強(qiáng)制重新請(qǐng)求」
        updateQuery, // 請(qǐng)求成功后立即調(diào)用,用于更新本地 store
    }
}
高級(jí)請(qǐng)求

我們僅改寫裝飾器部分

@graphql(query, {
    skip: props => !isValid(props),
    options: props => ({
        variables: {
            topicId: getIdFromUrl(),
        },
    }),
})

其中

skipshouldComponentUpdate 的效果是一樣的,決定是否 re-fetch。如果回調(diào)返回 false 直接不作請(qǐng)求。

options 返回一個(gè)函數(shù),用以設(shè)置請(qǐng)求的細(xì)節(jié),比如 variables 用于設(shè)置 query 參數(shù)

更詳細(xì)的文檔可以查閱

API: graphql container with queries | Apollo React Docs

GraphQL 入門: Apollo Client - 連接到數(shù)據(jù)

分頁請(qǐng)求

如文檔 Pagination | Apollo React Docs 所說,Apollo 支持兩種分頁

offset-based

按條數(shù)偏移量來請(qǐng)求分頁,請(qǐng)求時(shí)提供兩個(gè)參數(shù)

limit:相當(dāng)于 pageSize,一頁最多取多少個(gè)

offset: 條數(shù)偏移量,第 n 頁的 offset = limit * n

可見你需要自己維護(hù)一個(gè) pageNum: n 來實(shí)現(xiàn)按頁碼分頁

cursor-based

這是 Relay 風(fēng)格的請(qǐng)求,cursor 用于記錄下個(gè)請(qǐng)求開始時(shí),返回的第一個(gè)元素的位置,一般可以用該元素的 id 來標(biāo)識(shí)。

RESTful 風(fēng)格

我們后端并沒有采取上面任何一種,而是提供了一個(gè) pageInfo 對(duì)象,由前端傳入所需參數(shù),保持和 RESTful api 相似的風(fēng)格。

query.gql

#import "../gql/pageInfo.gql"
#import "@/gql/topic/userTopic.gql"

query topic($topicId: Int!, $pageNum: Int = 1) {
    community {
        topicEntity {
            listByTopicId(topicId: $topicId, pageSize: 10, pageNum: $pageNum) {
                pageInfo {
                    ...pageInfo
                }
                edges {
                    ...userTopicEntity
                }
            }
        }
    }
}

pageInfo.gql

fragment pageInfo on PageInfo {
    pageNum     # 頁碼
    pageSize    # 每頁條數(shù)
    pages       # 總頁數(shù)
    total       # 總條數(shù)
}

聲明下,由于我們只使用 GraphQL 的 Query 功能,所以沒研究過這種格式是否會(huì)影響 Mutation。現(xiàn)在或以后有 Mutation 需求的,盡量采用官方推薦的前兩種吧。

在組件內(nèi)進(jìn)行分頁請(qǐng)求

之前提到了, graphql 這個(gè)裝飾器為 this.props 添加了 data 對(duì)象,其中有個(gè)函數(shù)為 fetchMore

fetchMore 看名字就知道是用來作分頁請(qǐng)求的。

下面我們看一個(gè)比較真實(shí)的例子,許多業(yè)務(wù)相關(guān)的代碼都用表示其作用的函數(shù)替代了,注意看注釋:

import React, { PureComponent } from "react";
import { graphql } from "react-apollo";
import { select } from "./utils";
// 注意,這里用的 query 是 「RESTful 風(fēng)格」那一節(jié)中貼出的 schema
import query from "./query.gql";

@graphql(query, {
    skip: props => !isValid(props),
    options: props => ({
        variables: {
            topicId: getIdFromUrl(),
        },
    }),
})
@select({
    // 你可以寫一個(gè)函數(shù),從 this.props.data 里過濾出當(dāng)前列表的 pageInfo,直接添加到 this.props.pageInfo
    pageInfo: getPathInfoFromProps(props),
})
export default class TopicListContainer extends PureComponent {
    hasMore = () => {
        const { pageNum = 0, pages = 0 } = this.props.pageInfo || {};
        return pageNum < pages;
    }

    loadNextPage = () => {
        const { pageInfo = {}, data } = this.props;
        const { pageNum = 1 } = pageInfo;
        const fetchMore = data && data.fetchMore;

        if (!this.hasMore()) return;
        if (!fetchMore) return;

        return fetchMore({
            variables: {
                // 是的,這里不需要把你在 `@graphql` 裝飾器中定義的其它 variables 再寫一遍
                // apollo 會(huì)自動(dòng) merge
                pageNum: pageNum + 1,
            },
            // 這個(gè)回調(diào)函數(shù),會(huì)在 fetch 成功后自動(dòng)執(zhí)行,用于修改本地 apollo store
            updateQuery: (prev, { fetchMoreResult }) => {
                if (!fetchMoreResult) return prev;

                // 嘗試 log 下 `fetchMoreResult`,其返回的數(shù)據(jù)結(jié)構(gòu),和 query 中的 schmea 是一致的

                // parseNextData 返回新數(shù)據(jù)。
                // 新數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)必須和 query schema 一樣
                // NOTE: 此處會(huì)有大坑,如果你發(fā)現(xiàn)最終數(shù)據(jù)并未改變,請(qǐng)閱讀后文
                return parseNextData(prev, fetchMoreResult);
            }
        });
    }

    render() {
        return (
            
        );
    }
}

updateQuery 中,使用 parseNextData 經(jīng)過一些處理,返回新數(shù)據(jù)給 apollo,apollo 將把它寫入到 apollo store 中。
注意,這里至少會(huì)有兩處大坑

如果寫入失敗,是會(huì)靜默失敗的,也就是說 沒有任何報(bào)錯(cuò)提示

如果寫入數(shù)據(jù)的結(jié)構(gòu),和 query schema 不符,就會(huì)寫入失敗。

但寫入失敗的情況還不止于此!如果你發(fā)現(xiàn)最終數(shù)據(jù)并未改變,可能是中招了,解毒方案 請(qǐng)閱讀 寫入 store 的失敗原因分析和解決方案

這段代碼只演示了如何 被動(dòng) 地去修改本地的 apollo store 數(shù)據(jù),要問如何 主動(dòng) 去修改 apollo store,請(qǐng)看這篇文章: 修改本地的 apollo store 數(shù)據(jù)








文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/91924.html

相關(guān)文章

  • 21 分鐘學(xué) apollo-client 系列:擴(kuò)展 ApolloClient 的 api

    摘要:分鐘學(xué)是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。那怎么辦呢本章就教你非常簡(jiǎn)單地實(shí)現(xiàn)擴(kuò)展的。我們可以借鑒的的寫法,為的實(shí)例添加一些自己的方法。更重要的是,也會(huì)有的效果,上一個(gè)的輸出會(huì)成為下一個(gè)的輸入,便于組合。 21 分鐘學(xué) apollo-client 是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)修改本地的 ...

    levy9527 評(píng)論0 收藏0
  • 21 分鐘學(xué) apollo-client 系列:簡(jiǎn)單搭建

    摘要:分鐘學(xué)是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。其中提到了等需要后端配合的東西,徒增了配置的復(fù)雜性。如果不行,再跟隨我的簡(jiǎn)單步驟試試。環(huán)境要求請(qǐng)確保你已經(jīng)搭建了自己的環(huán)境下文在行號(hào)前添加表示刪除的原代碼,表示新增的代碼。 21 分鐘學(xué) apollo-client 是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)...

    ranwu 評(píng)論0 收藏0
  • 21 分鐘學(xué) apollo-client 系列:寫入失敗的原因和解決方案

    摘要:分鐘學(xué)是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。一旦你丟失了,可能會(huì)導(dǎo)致寫入失敗,或者盡管寫入了,但本該攜帶的那一層的數(shù)據(jù)沒有寫入。 21 分鐘學(xué) apollo-client 是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)修改本地的 apollo store 數(shù)據(jù)提供定制方案 請(qǐng)求攔截 封裝修改 clie...

    Baoyuan 評(píng)論0 收藏0
  • 21 分鐘學(xué) apollo-client 系列:apollo store 存儲(chǔ)細(xì)節(jié)

    摘要:分鐘學(xué)是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。內(nèi)部通過自己的私有沒有暴露給開發(fā)者來更新這個(gè)。相當(dāng)于這個(gè)就是自己維護(hù)的,它將所有通過得到的數(shù)據(jù)保存在這里。的生成規(guī)則根據(jù)官方文檔的說法,在創(chuàng)建時(shí),可選設(shè)置。如果不存在,則可能出現(xiàn)。 21 分鐘學(xué) apollo-client 是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。 搭建 Apollo client 端,集成 redux使用 apollo-client 來...

    lavor 評(píng)論0 收藏0
  • 21 分鐘學(xué) apollo-client 系列:請(qǐng)求攔截和 FragmentMatcher

    摘要:分鐘學(xué)是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。接管了請(qǐng)求和狀態(tài)管理。一般在生產(chǎn)環(huán)境中,我們通常還希望做權(quán)限驗(yàn)證請(qǐng)求攔截等事務(wù)處理。 21 分鐘學(xué) apollo-client 是一個(gè)系列,簡(jiǎn)單暴力,包學(xué)包會(huì)。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)修改本地的 apollo store 數(shù)據(jù)提供定制方案 請(qǐng)求攔截 封裝修改 clie...

    Eastboat 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<