国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

21 分鐘學 apollo-client 系列:修改本地 store 數(shù)據(jù)

617035918 / 803人閱讀

摘要:分鐘學是一個系列,簡單暴力,包學包會。搭建端,集成使用來獲取數(shù)據(jù)修改本地的數(shù)據(jù)提供定制方案請求攔截封裝修改的存儲細節(jié)寫入的失敗原因分析和解決方案修改本地數(shù)據(jù)之前我們已經(jīng)知道,我們可以在請求結束之后,通過自動執(zhí)行的回調,修改。

21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。

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

請求攔截

封裝修改 client 的 api

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

修改本地 store 數(shù)據(jù)

之前我們已經(jīng)知道,我們可以在請求結束之后,通過自動執(zhí)行 fetchMoreupdateQuery 回調,修改 apollo store。

那么,如何在不觸發(fā)請求的情況下,主動修改 apollo store 呢?

也許你會說通過 redux 的方式,dispatch 一個 action,由 reducer 來處理,但因為 apollo store 的數(shù)據(jù)存儲方案,這會相當麻煩。
詳細原理請看這一小節(jié) apollo store 存儲細節(jié)

read & write

Apollo 對此,提供了兩組命令式 api read/writeQueryread/writeFragment

詳見其文檔:DataProxy
或者這篇中文文檔:GraphQL 入門: Apollo Client 存儲API

讀完這兩篇文檔,你大概就能掌握修改 apollo store 的技巧。

不過其中還是有不少值得注意的點,下面通過代碼和注釋來體會:

import React, { PureComponent } from "react";
import TodoQuery from "./TodoQuery";
import TodoFragment form "./TodoFragment";
import { withApollo, graphql } from "react-apollo";

@graphql(TodoQuery)
@withApollo // 通過 props 讓組件可以訪問 client 實例
class TodoContainer extends PureComponent {
    handleUpdateQuery = () => {
        const client = this.props.client;
        const variables = {
            id: 5
        };

        const data = client.readQuery({
            variables,
            query: TodoQuery,
        });

        const nextData = parseNextData(data);

        client.writeQuery({
            variables,
            query: TodoQuery,
            data: nextData,
        });
    }

    handleUpdateFragment = () => {
        const client = this.props.client;

        const data = client.readFragment({
            id: "Todo:5",
            fragment: TodoFragment,
            fragmentName: "todo", // fragment 的名字,必填,否則可能會 read 失敗
        });

        const nextData = parseNextData(data);

        client.writeFragment({
            id: "Todo:5",
            fragment: TodoFragment,
            fragmentName: "todo",
            data: nextData,
        });
    }
}

不過,還是需要注意,它們和 fetchMore 里的 updateQuery 一樣,都存在靜默失敗和寫入限制。
如果你發(fā)現(xiàn)數(shù)據(jù)沒有被更新,嘗試看我給出的解讀和解毒方案: 寫入 store 的失敗原因分析和解決方案

你可能還注意到了 read/writeFragment 時,其 id 并不是簡單的 5,而是 ${__typename}:5 。
這和 apollo store 存儲數(shù)據(jù)的方式有關,我在 apollo store 存儲細節(jié) 詳述了 apollo store 存儲數(shù)據(jù)的原理。

在此處,你只需要知道,這里 id 的值應當與你在創(chuàng)建 apollo client 時設置的 dataIdFromObject 有關,如果沒有設置,默認為 ${__typename}:${data.id}
最好的方式是調用 client.dataIdFromObject 函數(shù)計算出 id

const { id, __typename } = data;
const id = client.dataIdFromObject({
    id,
    __typename,
});
簡化接口

不過你不覺得上面這種寫法相當麻煩嗎?

雖然先 read 再 write 比較原子化,但是考慮到大部分場景下我們只需要 update 就可以了,參數(shù)這么傳來傳去相當麻煩,更不用說會寫太多重復的代碼。
所以咱們可以寫一個 updateQuery、updateFragment 函數(shù)。

enhancers.js

import client from "./client";

function updateFragment(config) {
    const { id: rawId, typename, fragment, fragmentName, variables, resolver } = config;
    // 默認使用 fragmentName 作為 __typename
    const __typename = typename || toUpperHeader(fragmentName);
    const id = client.dataIdFromObject({
        id: rawId,
        __typename,
    });
    const data = client.readFragment({ id, fragment, fragmentName, variables });
    const nextData = resolver(data);

    client.writeFragment({
        id,
        fragment,
        fragmentName,
        variables,
        data: nextData,
    });

    return nextData;
}

function updateQuery(config) {
    const { variables, query, resolver } = config;
    const data = client.readQuery({ variables, query });
    const nextData = resolver(data);
    client.writeQuery({
        variables,
        query,
        data: nextData,
    });
    return nextData;
};

function toUpperHeader(s = "") {
    const [first = "", ...rest] = s;
    return [first.toUpperCase(), ...rest].join("");
}

如此,我們可以這樣簡化之前的代碼

import React, { PureComponent } from "react";
import TodoQuery from "./TodoQuery";
import TodoFragment form "./TodoFragment";
import { withApollo, graphql } from "react-apollo";
import { updateQuery, updateFragment } from "@/apollo/enhancers";

@graphql(TodoQuery)
@withApollo // 通過 props 讓組件可以訪問 client 實例
class TodoContainer extends PureComponent {
    handleUpdateQuery = () => {
        return updateQuery({
            variables:  {
                id: 5
            },
            query: TodoQuery,
            resolver: data => parseNextData(data),
        });
    }

    handleUpdateFragment = () => {
        return updateFragment({
            id: 5,
            typename: "Todo",
            fragment: TodoFragment,
            fragmentName: "todo",
            resolver: data => parseNextData(data);
        });
    }
}

其中,resolver 是一個數(shù)據(jù)處理函數(shù),它接收 read 操作后的 data ,返回的 nextData 將用于 write 操作。
這種簡單的 update 場景其實是更常見的,且你仍然可以在 resolver 中進行 debug,可以說代碼相當精簡了。

注冊為 client api

在 封裝修改 client 的 api 里我們提到可以使用 enhancer 的方式為 client 添加接口,如果你懶得每次都 import 這兩個函數(shù),那么不妨將他們注冊為 client 的實例方法:

enhancers.js

const enhancers = [
    updateFragmentFactory,
    updateQueryFactory,
];

export default function applyEnhancers(client) {
    // 更函數(shù)式的寫法是把 enhancers 也作為參數(shù)傳進來,但是我需要的 enhancer 比較少,做此精簡
    return enhancers.reduce(
        (result, enhancer) => enhancer(result),
        client
    );
}

// --- enhancers ---
function updateFragmentFactory(client) {
    return function updateFragment(config) {
        // ...
    }

    return client;
}

function updateQueryFactory(client) {
    return function updateQuery(config) {
        // ...
    };

    return client;
}

這樣你就可以直接從 client 實例中訪問這兩個函數(shù)了。

提示:在組件中只需 withApollo 即可添加 clientprops 中。








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

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91921.html

相關文章

  • 21 分鐘 apollo-client 系列:apollo store 存儲細節(jié)

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

    lavor 評論0 收藏0
  • 21 分鐘 apollo-client 系列:寫入失敗的原因和解決方案

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

    Baoyuan 評論0 收藏0
  • 21 分鐘 apollo-client 系列:獲取數(shù)據(jù)

    摘要:分鐘學是一個系列,簡單暴力,包學包會。一旦組件掛載后,會自動進行數(shù)據(jù)請求,前提是客戶端提供的和后端的相符。如果回調返回直接不作請求。在組件內進行分頁請求之前提到了,這個裝飾器為添加了對象,其中有個函數(shù)為。 21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)修改本...

    robin 評論0 收藏0
  • 21 分鐘 apollo-client 系列:擴展 ApolloClient 的 api

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

    levy9527 評論0 收藏0
  • 21 分鐘 apollo-client 系列:簡單搭建

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

    ranwu 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<