Initializing local state with an array stores incorrect value in the cache
See original GitHub issueWhen writing data to the cache directly via cache.writeData
, empty arrays are stored as follows:
cartItems: {"type":"json","json":[]}
This can be seen with Apollo’s Full Stack Tutorial in Section 8: Managing Local State.
Cause
This appears to be caused by apollo-client-inmemory
’s behavior in writeFieldToStore:
For local state, there will be no selectionSet
and typeof [] === "object"
. Perhaps the Array.isArray()
check should preceed !field.selectionSet || value === null
?
Reproduction
-
Check out Apollo’s full stack tutorial from GitHub
-
cd
tofinal/server
- Install dependencies via
npm ci
and run the projectnpm start
- Install dependencies via
-
In a second terminal,
cd
tofinal/client
- Install dependencies via
npm ci
and run the projectnpm start
- Install dependencies via
-
Load the browser, check the cache with Apollo Client DevTools
Versions
This can be reproduced both with the latest stable releases and with the latest v2.5 release candidate (rc2, February 25th)
Issue Analytics
- State:
- Created 5 years ago
- Reactions:19
- Comments:6 (1 by maintainers)
Top Results From Across the Web
Local State Management with Reactive Variables
For starters, here's how to initialize a default value for a name field on the Person type. const cache = new InMemoryCache({ typePolicies:...
Read more >How to Initialize State for each Element in Array ReactJS
The solution for me was running the function in componentDidUpdate. My state now initializes correctly. Thanks again Junius for the help!
Read more >Local Storage in React - Robin Wieruch
If there is no value in the local storage, we default to false for the initial state. The proposed solution works if local...
Read more >State Management within React Functional Components with ...
We'll look at managing component state and local variables ... Your components can bind to the value of isAuthenticated. ... Return cached value...
Read more >C++ Tutorial: Memory Allocation - 2020 - BogoToBogo
Parameters are local variables which are initialized with an assignment ... computers have three locations for storing data - physical memory, cache, ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
This behavior is especially troubling if the empty array is a child of an object in a collection. If the first child array is empty, objects in other children are stored a
json
, not as objects. This causes queries that reference those children to error.Example:
If I have this schema:
And I fetch all the parents, and store them in a
stuff @client
cache, it will look like this if the first parent returned has no children:Any query that includes:
will error with
Error: Network error: Can't find field name on object undefined.
This is causing some serious issues in our app.After some digging I found out how to solve half of the problem. Since I’m using
writeQuery
to initialize theParent
object I had to pass along agql
which is where the problem was for the children array.I was using this query to write in cache
to store following data:
This as we already know from the posts above results in an error because the array is stored in cache like this:
However if you modify the query to include all the fields on the children object like this:
and use it with
.writeQuery
it will actually create an empty array instead of json:This is because apollo needs a
selectionSet
to be able to save it as anarray
rather thanjson
.But as I mentioned, this covers only half of the problem, because simple arrays such as:
will still get stored as json: