21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。javascript
搭建 Apollo client 端,集成 redux
使用 apollo-client 來獲取數據
修改本地的 apollo store 數據
提供定製方案java
同志們注意啦!整個 apollo 的坑都集中在這裏啦!redux
一旦返回的數據寫入 apollo store 失敗,會 靜默失敗 ,最終你發現怎麼數據沒有發生任何變化? (坑爹啊!)segmentfault
一個簡單的辦法是,你去 node_modules 下,把報錯信息暴露出來。是的,通過閱讀源碼,我發現這已是最簡單的辦法了...後端
具體代碼在 node_modules\apollo-client\data\writeToStore.js
api
若是這解決了你的問題,請給我打賞,謝謝。fetch
那何時會寫入失敗呢?ui
1. 寫入的數據,其結構不符合 query schema
這意味着你不能基於 query schema 添加一些你本地須要的數據,好比 isSelected 什麼的spa
2. 丟失 __typename
信息
不能丟失任何層級上的 __typename
!
當你 log fetchMoreResult
你會發現,它在不少層級上附帶了 __typename
,這個數據用於檢查寫入數據是否匹配 query schema。
一旦你丟失了 __typename
,可能會致使寫入失敗,或者儘管寫入了,但本該攜帶 __typename
的那一層的數據沒有寫入。
你可能說,那我小心一點,老是使用 Object.assign
或者 { ...obj, a: 1 }
這種 spread 賦值的方式吧。
年輕人,你仍是太天真啊!
若是你獲得一組數據,嵌套的某一個值爲 null
,那麼它原本就不攜帶 __typename
!
若是這個值爲 null
的數據在你的 query schema 中確實須要 __typename
,那即便你對這個數據從新賦值,也沒法被寫入到 apollo store 中,由於缺乏 __typename
信息。
上面這段話比較繞,給你看個例子。
假設你有這樣一個 query
query { user { # typename 爲 User id nickname statistic { # typename 爲 UserStatistic upvoted } } }
而後,獲得一組數據
const prev = { user: { __typename: 'User', id: 1, nickname: 'apollo 真是坑爹啊', statistic: null } }
爲了 ui 顯示正常,你會給 statistic 設置一些默認值
const next = { ...prev, user: { ...prev.user, statistic: { upvoted: false, } } }
若是你將 next 數據 writeToStore 你就會就發現 statistic 仍是爲 null
,這些數據仍是沒有被寫入 apollo store。
這是由於,user.statistic
在 schema 中定義的 type 是 UserStatistic
,而原始數據因爲爲 null
,因此本該自動附加的 __typename
屬性也不存在。這致使你在寫入 store 的時候,缺乏了必要的 __typename
信息,apollo 將拒絕接受。
很扯吧。
要讓上面的代碼 work 起來,你須要
const next = { ...prev, user: { ...prev.user, statistic: { upvoted: false, + __typename: 'UserStatistic', } } }
若是沒有報錯消息的話,上面這種狀況是極其難以排查的,尤爲是咱們特別容易遇到缺乏 __typename
的場景。
爲了減小此類事故的發生,你能夠
__typename