最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Apollo Client replaces an array of objects with the same id and different values with an array of copies of the fir

programmeradmin1浏览0评论

Our GraphQL server responds to a query with data that includes an array of objects each of which shares the same id and different values for a different key. For instance, we might have an array that looks like:

[
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 6 },
  { id: 123, name: 'foo', type: 'bar', cost: 7 },
  { id: 123, name: 'foo', type: 'bar', cost: 8 }
]

We can see in the Network tab that the response from the server has the correct data in it. However, by the time it goes through processing by the Apollo Client module the array has been transformed into something that might look like this:

[
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 }
]

Essentially what we're seeing is that if all of the objects in an array share the same value for id then all objects in the array bee copies of the first object in the array.

Is this the intended behavior of Apollo Client? We thought maybe it had something to do with incorrect caching, but we were also wondering if maybe Apollo Client assumed that subsequent array members with the same id were the same object.

Our GraphQL server responds to a query with data that includes an array of objects each of which shares the same id and different values for a different key. For instance, we might have an array that looks like:

[
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 6 },
  { id: 123, name: 'foo', type: 'bar', cost: 7 },
  { id: 123, name: 'foo', type: 'bar', cost: 8 }
]

We can see in the Network tab that the response from the server has the correct data in it. However, by the time it goes through processing by the Apollo Client module the array has been transformed into something that might look like this:

[
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 },
  { id: 123, name: 'foo', type: 'bar', cost: 5 }
]

Essentially what we're seeing is that if all of the objects in an array share the same value for id then all objects in the array bee copies of the first object in the array.

Is this the intended behavior of Apollo Client? We thought maybe it had something to do with incorrect caching, but we were also wondering if maybe Apollo Client assumed that subsequent array members with the same id were the same object.

Share Improve this question asked Oct 25, 2017 at 17:45 natlee75natlee75 5,1973 gold badges36 silver badges39 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 6

It looks like this is behavior as intended. The Apollo Client normalizes on id.

As the other answer suggests this happens because Apollo normalises by ID. There's a very extensive article on the official blog that explains the rationale of it, along with the underlying mechanisms.

In short, as seen by Apollo's cache, your array of objects contains 4 instances of the same Object (id 123). Same ID, same object.

This is a fair assumption on Apollo's side, but not so much in your case. You have to explicitly tell Apollo that these are indeed 4 different items that should be treated differently.

In the past we used dataIdFromObject, and you can see an example here.

Today, you would use typePolicies and keyfields:

const cache = new InMemoryCache({
  typePolicies: {
    YourItem: {
      // Combine the fields that make your item unique
      keyFields: ['id', 'cost'],
    }
  },
});

Docs

I have the same issue. My solution is to set fetchPolicy: "no-cache" just for this single API so you don't have to change the InMemoryCache. Note that setting fetchPolicy to network-only is insufficient because it still uses the cache.

fetchPolicy document

It works for me: const cache: InMemoryCache = new InMemoryCache({ dataIdFromObject: o => false )};

previous answer solves this problem too! Also you can change the key name(for example id => itemId) on back-end side and there won't be any issue!

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>