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

Fix crash in unsubscribeFromQuery #260

Merged
merged 1 commit into from
Oct 11, 2016
Merged

Conversation

glasser
Copy link
Member

@glasser glasser commented Oct 11, 2016

Also delete querySubscription when there is no subscription, since that
seems reasonable.

See #255.

@tmeasday
Copy link
Contributor

@glasser do you know what the circumstance that leads to this bug is? Seems likely to be either:

a) component receives new props before it has mounted
b) component unmounts before it has mounted.

Neither seems like valid react lifecycle but I'm not initimately aware of the rules surrounding it. Can we figure out which it is so we can add a test?

@glasser glasser force-pushed the glasser/unsubscribe-crash branch 2 times, most recently from 1036a23 to baa329f Compare October 11, 2016 01:41
@tmeasday tmeasday force-pushed the glasser/unsubscribe-crash branch 2 times, most recently from 34032af to c2af14a Compare October 11, 2016 04:30
@tmeasday
Copy link
Contributor

@glasser I ended up getting rid of promise code, not really needed in jasmine (I had my mocha hat on).

@tmeasday tmeasday assigned glasser and unassigned tmeasday Oct 11, 2016

networkInterface.query = (request) => {
console.log('failing')
fail(new Error('query ran even though skip present'));
Copy link
Member Author

@glasser glasser Oct 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't figure out what fail is. It's not in https://facebook.github.io/jest/docs/api.html or defined in the file. But it does seem to work (I tested with the change reverted...)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess fail is a Jasmine thing. Jest's docs seem a bit incomplete.

@@ -495,6 +614,44 @@ describe('queries', () => {
renderer.create(<ProviderMock client={client}><ChangingProps /></ProviderMock>);
});


fit('allows you to unmount a skipped query', (done) => {
Copy link
Member Author

@glasser glasser Oct 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing to it

const oldQuery = networkInterface.query;

networkInterface.query = (request) => {
console.log('failing')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this line

renderer.create(<ProviderMock client={client}><Parent /></ProviderMock>);
});

it('allows you to skip then unskip a query with opts syntax', (done) => {
Copy link
Member Author

@glasser glasser Oct 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one wasn't actually failing (without the code change). Or maybe it was failing if you only reverted one bit of the code change but not the whole commit.

I've made it longer and more detailed, but then it doesn't actually pass any more: looks like I can't convince it to run the query again. Maybe that's due to some caching and that's a feature? I guess @tmeasday is asleep now; @jbaxleyiii want to take a look at my version of this test and help me figure out how to get it to fail? The goal is to trigger a now-fixed bug where the check on opts.skip in subscribeToQuery doesn't delete querySubscription and thus never re-subscribes when unskipped.

networkInterface.query = (request) => {
console.log('failing')
fail(new Error('query ran even though skip present'));
return oldQuery(request);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lack of preserving this caused problems when I copied this into other test. fixed.

@glasser glasser force-pushed the glasser/unsubscribe-crash branch 2 times, most recently from a364db1 to 6845cb8 Compare October 11, 2016 16:40
See #255.

@glasser and I found a few bugs around the (old and new) skip options,
and wrote some tests to confirm the fixes and stop regressions

- didn't delete querySubscription in .unsubscribeFromQuery()
  - this mean if you skipped and then unskipped, it would break

- not checking for querySubscription before .unsubscribe on unmounting
  - if you skip then unmount, you have problem

- check for non-skip -> skip in willReceiveProps didn't return in the remain skipping case
  - mean "non skipping" code ran when remaining skipping.

- Make the default data have an "errors" null field rather than "error"
  since that matches what is done elsewhere.

- Also make sure to consistently set it to null rather than undefined.

- Be a little more consistent about how we initialize and re-initialize
  this.data; for example, if we use the deprecated skip option to change
  an unskipped query to a skipped query, include "error: null" as well,
  and if we are switching from unskip to skip to unskip, make sure to
  re-initialize the full data object.
@glasser glasser assigned tmeasday and jbaxleyiii and unassigned glasser Oct 11, 2016
@glasser
Copy link
Member Author

glasser commented Oct 11, 2016

OK, I put a little more effort into this and got all the new tests to pass (and to fail without the graphql.tsx changes). This involved a few more changes to the real code, all of which I think are bug fixes, but I'm looking at all this code for the first time and I might be wrong! I'd love another round of review from @jbaxleyiii or @tmeasday or anyone familiar with the code!

@tmeasday
Copy link
Contributor

tmeasday commented Oct 11, 2016

I wonder if rather than adding and removing the observable query fields from this.data we should instead just blindly pass skippedQueryData to the component at render time (in the skip case)?

@tmeasday
Copy link
Contributor

Or do we need the other parts of initializeData() (the currentResult part) also when skip->unskipping?

@tmeasday
Copy link
Contributor

Or maybe we should just copy the properties over at render time and not attach them to data in the first place. I might do that.

In any case, I am good with these changes. Merging.

@tmeasday tmeasday merged commit d6e110b into master Oct 11, 2016
@glasser
Copy link
Member Author

glasser commented Oct 11, 2016

The main thing i was going for by inserting the initializeData call in subscribeToQuery was to ensure that when you "unskip" that you end up with loading: true set even though it was false previously because of the skipping. I don't 100% understand every bit of this code so my intuition may be off.

I think the idea of handling skipping directly in render makes sense.

@tmeasday
Copy link
Contributor

I think we can go a bit further and actually not cache this.data at all. It should make things simpler and more declarative (and delegate more work to AC): #264

@calebmer calebmer deleted the glasser/unsubscribe-crash branch March 1, 2017 18:28
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.

3 participants