Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Change the default query data state from {} to undefined #3388

Merged
merged 1 commit into from Aug 23, 2019
Merged

Conversation

hwillson
Copy link
Member

React Apollo returns an empty object for the initial data value, that is returned when performing a query. There a long history behind why this is the case, but this single issue has caused a lot of frustration over the past long while due to the following:

  • {} is not the same as having no data; it's an object, not nothing. If there is no data, we shouldn't pretend there is.
  • Setting data to {} isn't followed in all cases; e.g. when errors occur, during parts of SSR, when skipping, etc. This leads to developers having to know when to expect {} and when to expect undefined.
  • Forcing no data situations to be empty objects can go against application schemas that enforce a value and don't allow empty objects.

This PR adjusts React Apollo's default query data state to be undefined, and will no longer convert data to an empty object if the returned data is falsy. Using undefined as the initial state has also been aligned across all parts of RA querying, including SSR.

Unfortunately, we missed the opportunity to address this as part of the React Apollo 3.0 launch. This change can be considered breaking, and we can't do another major version bump to get this
in (3.0 is the last major version of React Apollo, as React Apollo is being merged into the Apollo Client project). We'll have to put some thought into how we can roll this out.

Fixes #3323.

@dnbkr
Copy link

dnbkr commented Aug 20, 2019

Hi,

With regards to this being a breaking change, I'm not sure what your yardstick is for that, but the typescript definition of data is TData | undefined so as far as the TS defs are concerned, this would not be a breaking change

@hwillson
Copy link
Member Author

Agreed @coffeedoughnuts, but for the people who aren't using TS and are expecting data to always be initialized as an empty object, this could be breaking. Their data.something references could now result in Uncaught TypeError's.

That being said, I do want to get this change in (and sooner than later). If anyone reading this has had a chance to try out the 3.1.0-beta.0's that include this PR, and can let us know if things look okay, then we should be good to go here. Thanks!

React Apollo returns an empty object for the initial `data` value,
that is returned when performing a query. There a long history
behind why this is the case, but this single issue has caused a
lot of frustration over the past long while due to the following:

- `{}` is not the same as having no data; it's an object, not
  nothing. If there is no data, we shouldn't pretend there is.
- Setting `data` to `{}` isn't followed in all cases; e.g. when
  errors occur, during parts of SSR, when skipping, etc. This leads
  to developers having to know when to expect `{}` and when to
  expect `undefined`.
- Forcing no data situations to be empty objects can go against
  application schemas that enforce a value and don't allow
  empty objects.

This commit adjusts React Apollo's default query `data` state to
be `undefined`, and will no longer convert `data` to an empty
object if the returned data is falsy. Using `undefined` as the
initial state has also been aligned across all parts of RA
querying, including SSR.

Unfortunately, we missed the opportunity to address this as part
of the React Apollo 3.0 launch. This change can be considered
breaking, and we can't do another major version bump to get this
in (3.0 is the last major version of React Apollo, as React
Apollo is being merged into the Apollo Client project). We'll
have to put some thought into how we can roll this out.

Fixes #3323.
@FezVrasta
Copy link

The type error could happen in a whole set of cases as stated by your original post. That means this PR would just make this error surface earlier.

I wouldn't consider this a breaking change.

@mekhami
Copy link

mekhami commented Sep 9, 2019

I believe this change broke this pattenr that I'd seen and used for quite some time:

const { loading, data: { myQueryResult }} = useQuery(QUERY)

Now, it throws an error rather than myQueryResult being undefined until the loading was complete.

Is this really needed behavior?

@FezVrasta
Copy link

FezVrasta commented Sep 9, 2019

@mekhami that's the kind of stuff I mentioned in my post above, your code could have thrown a type error in some cases, now it throws a type error in all the cases. (which I think is a good thing)

You can change it to:

const { loading, data: { myQueryResult } = {}} = useQuery(QUERY)

if you like this kind of behavior

@pleunv
Copy link

pleunv commented Sep 11, 2019

I'm assuming this doesn't have any implications on @apollo/react-hoc, since the data prop there contains additional fields like error, loading, networkStatus and so on?

@avindra
Copy link

avindra commented Sep 13, 2019

Thanks for this change. Better to align it sooner rather than later.

As @FezVrasta mentioned, if you are destructuring the data, you can just assign the default value as {} to get the previous behavior.

@drewandrew
Copy link

From what I can read in the Apollo Client 3 beta docs, it sounds like data will default to undefined just as this PR outlines. I'm wondering if someone could confirm this here.

@lifeiscontent
Copy link

@drewandrew that's correct!

@spawnia
Copy link

spawnia commented Mar 26, 2020

This has caused us quite a bit of grief. Please stick to semantic versioning, even when there are aesthetic/political reasons that say otherwise.

@onpaws
Copy link

onpaws commented Apr 20, 2020

Thanks @FezVrasta for the tip, at first wasn't sure how to cleanly handle this change but your little trick is working great for my apps needs

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

useQuery: data should be undefined while loading for the first time
10 participants