Repository: FormidableLabs/urql
Pull request #387 (2019-08-13 07:57:49)

(chore) - remove useDevtoolsContext
Relies on publishing of: https://github.com/FormidableLabs/urql-devtools-exchange/pull/1

Removes 60gzipped bytes

parkerziegler: Looks great to me @JoviDeCroock! Definitely merge ready once FormidableLabs/urql-devtools-exchange#1 is published!
andyrichardson: I've merged your changes in `urql-devtools-exchange`!
andyrichardson: I think we should hold off merging this until the devtools exchange changes have been published
kitten: @andyrichardson definitely 👍 otherwise we'd diverge and we don't want that confusion on master for sure 

Patch:
diff --git a/README.md b/README.md
index 870ed3f0..14d2e94f 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,9 @@
   <a href="https://github.com/FormidableLabs/urql#maintenance-status">
     <img alt="Maintenance Status" src="https://img.shields.io/badge/maintenance-active-green.svg" />
   </a>
+  <a href="https://spectrum.chat/urql">
+    <img alt="Spectrum badge" src="https://withspectrum.github.io/badge/badge.svg" />
+  </a>
 
   <br />
   <br />
diff --git a/docs/api.md b/docs/api.md
index 7aaa576e..3ab2e460 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -1,8 +1,15 @@
+---
+title: API
+order: 6
+---
+
+<a name="api"></a>
+
 # API
 
 ## React components and hooks
 
-### `useQuery` (hook)
+### useQuery (hook)
 
 Accepts a single options object as input:
 
@@ -34,9 +41,9 @@ interface UseQueryState<T> {
 And the `executeQuery` function optionally
 accepts a partial `OperationContext`.
 
-[More information on how to use this hook can be found in the Getting Started section.](getting-started.md#writing-queries)
+[More information on how to use this hook can be found in the Getting Started section.](https://formidable.com/open-source/urql/docs/getting-started#writing-queries)
 
-### `useMutation` (hook)
+### useMutation (hook)
 
 Accepts a single `query` argument of type `string`. And returns the
 current mutation's state and an `executeMutation` function in a tuple. The
@@ -59,9 +66,9 @@ interface UseMutationState<T> {
 The `executeMutation` function accepts the `variables` of type `object` and
 an optional `context` variable of type `Partial<OperationContext>`.
 
-[More information on how to use this hook can be found in the Getting Started section.](getting-started.md#writing-mutations)
+[More information on how to use this hook can be found in the Getting Started section.](https://formidable.com/open-source/urql/docs/getting-started#writing-mutations)
 
-### `useSubscription` (hook)
+### useSubscription (hook)
 
 Accepts an options argument as its first input, and a second optional argument that is
 the subscription handler function.
@@ -95,11 +102,11 @@ interface UseSubscriptionState<T> {
 }
 ```
 
-[More information on how to use this hook can be found in the Basics section.](basics.md#subscriptions)
+[More information on how to use this hook can be found in the Basics section.](https://formidable.com/open-source/urql/docs/basics#subscriptions)
 
-### `Query` (component)
+### Query (component)
 
-[More information on how to use this component can be found in the Getting Started section.](getting-started.md#writing-queries)
+[More information on how to use this component can be found in the Getting Started section.](https://formidable.com/open-source/urql/docs/getting-started#writing-queries)
 
 #### Props
 
@@ -123,9 +130,9 @@ interface UseSubscriptionState<T> {
 | extensions   | `?Record<string, any>`              | Optional extensions that the GraphQL server may have returned.                                          |
 | executeQuery | `Partial<OperationContext> => void` | A function that can force the operation to be sent again with the given context (Useful for refetching) |
 
-### `Mutation` (component)
+### Mutation (component)
 
-[More information on how to use this component can be found in the Getting Started section.](getting-started.md#writing-mutations)
+[More information on how to use this component can be found in the Getting Started section.](https://formidable.com/open-source/urql/docs/getting-started#writing-mutations)
 
 #### Props
 
@@ -144,9 +151,9 @@ interface UseSubscriptionState<T> {
 | extensions      | `?Record<string, any>`                                             | Optional extensions that the GraphQL server may have returned.   |
 | executeMutation | `(variables: object, context?: Partial<OperationContext>) => void` | A function that accepts variables and starts the mutation        |
 
-### `Subscription` (component)
+### Subscription (component)
 
-[More information on how to use this component can be found in the Basics section.](basics.md#subscriptions)
+[More information on how to use this component can be found in the Basics section.](https://formidable.com/open-source/urql/docs/basics#subscriptions)
 
 #### Props
 
@@ -175,7 +182,7 @@ be used in combination with the `useContext` hook.
 
 ## The Client and related types
 
-### `Client` (class)
+### Client (class)
 
 The client manages all operations and ongoing requests to the exchange pipeline.
 It accepts a bunch of inputs when it's created
@@ -190,7 +197,7 @@ It accepts a bunch of inputs when it's created
 
 `urql` also exposes `createClient()` that is just a convenient alternative to calling `new Client()`.
 
-#### `.executeQuery()`, `.executeSubscription()`, and `.executeMutation()`
+#### .executeQuery(), .executeSubscription(), and .executeMutation()
 
 These methods are used by `<Query>` & `useQuery()`, `<Subscription>` & `useSubscription()`,
 and `<Mutation>` & `useMutation()` respectively.
@@ -202,7 +209,7 @@ Internally they then create an `Operation` and call `.executeRequestOperation()`
 the `Operation`. This then returns a `Source<OperationResult>`, i.e. a stream of
 `OperationResult`s.
 
-#### `.executeRequestOperation()`
+#### .executeRequestOperation()
 
 This method accepts an `Operation` and handles the flow of said `Operation`. Every `Operation`
 that is executed must pass through this method.
@@ -229,7 +236,7 @@ is dispatched.
 
 The return value is the filtered `Source<OperationResult>`.
 
-#### `.reexecuteOperation()`
+#### .reexecuteOperation()
 
 This method accepts an `Operation` and will dispatch this `Operation` if there
 are any subscriptions from `executeRequestOperation`'s `Source<OperationResult>`
@@ -238,7 +245,7 @@ to this particular `Operation`.
 This is called by `cacheExchange` when an `Operation`'s `OperationResult` is
 invalidated in the cache.
 
-#### `.createRequestOperation()`
+#### .createRequestOperation()
 
 This is called by the `executeQuery`, `executeSubscription` and `executeMutation`
 methods to create `Operation`s. It accepts:
@@ -249,7 +256,7 @@ methods to create `Operation`s. It accepts:
 
 It returns an `Operation`.
 
-#### `.dispatchOperation()`
+#### .dispatchOperation()
 
 This method dispatches an `Operation` to the exchange pipeline. This is only
 used directly by the Client and shouldn't normally be called externally, except
@@ -258,7 +265,7 @@ when the tracking logic of active `Operation`s needs to be bypassed.
 These `Operation`s are streamed from the `operations$: Source<Operation>` stream.
 The results of all exchanges are similarly output to `results$: Source<OperationResult>`.
 
-### `OperationType` (type)
+### OperationType (type)
 
 This determines what _kind of operation_ the exchanges need to perform.
 This can either be:
@@ -272,7 +279,7 @@ The `'teardown'` operation is special in that it instructs exchanges to cancel
 any ongoing operations with the same key as the `'teardown'` operation that is
 received.
 
-### `RequestPolicy` (type)
+### RequestPolicy (type)
 
 This determines the strategy that a cache exchange should use to fulfill an operation.
 When you implement a custom cache exchange it's recommended that these policies are
@@ -283,7 +290,7 @@ handled.
 - `'network-only'`
 - `'cache-and-network'`
 
-### `GraphQLRequest` (type)
+### GraphQLRequest (type)
 
 This often comes up as the **input** for every GraphQL request.
 It consists of `query` and optional `variables`.
@@ -300,7 +307,7 @@ As can be seen it also carries a `key` property. This property
 is a hash of both the `query` and the `variables`, to uniquely
 identify the request.
 
-### `OperationContext` (type)
+### OperationContext (type)
 
 This type is used to give an operation additional metadata and information.
 
@@ -317,7 +324,7 @@ It contains a lot of the above mentioned Client options and also `requestPolicy`
 It accepts additional, untyped parameters that can be used to send more
 information to custom exchanges.
 
-### `Operation` (type)
+### Operation (type)
 
 The input for every exchange that informs GraphQL requests.
 it's essentially an extension of the `GraphQLRequest`.
@@ -335,7 +342,7 @@ type Operation = {
 The `key` value is a "hash" of `query` and `variables` or another string that
 unique identifies the combination of the two.
 
-### `OperationResult` (type)
+### OperationResult (type)
 
 The result of every GraphQL request, i.e. an `Operation`.
 It's very similar to what comes back from a typical GraphQL API, but
@@ -350,7 +357,7 @@ type OperationResult = {
 };
 ```
 
-### `CombinedError` (class)
+### CombinedError (class)
 
 | Input         | Type                             | Description                                                                       |
 | ------------- | -------------------------------- | --------------------------------------------------------------------------------- |
@@ -366,7 +373,7 @@ that a GraphQL result might have normally.
 
 ## Exchanges and their utilities
 
-### `ExchangeInput` (type)
+### ExchangeInput (type)
 
 ```js
 type ExchangeInput = {
@@ -375,7 +382,7 @@ type ExchangeInput = {
 };
 ```
 
-### `ExchangeIO` (type)
+### ExchangeIO (type)
 
 A function that receives a stream of operations and must return a stream
 of results.
@@ -384,7 +391,7 @@ of results.
 type ExchangeIO = (Source<Operation>) => Source<OperationResult>;
 ```
 
-### `Exchange` (type)
+### Exchange (type)
 
 Similar to `redux-observable`'s epics, kind of related to Apollo's links,
 also somehow similar to Express' middleware.
@@ -398,7 +405,7 @@ Exchanges can therefore be chained. They can alter and filter `Operation`s
 that go into the next exchange, and they can alter, filter, or return
 `OperationResult`s that are returned.
 
-### `composeExchanges` (function)
+### composeExchanges (function)
 
 This utility accepts multiple exchanges and composes them into a single one.
 It chains them in the order that they're given, left to right.
@@ -410,23 +417,23 @@ function composeExchanges(Exchange[]): Exchange;
 This can be used to combine some exchanges and is also used by `Client`
 to handle the `exchanges` input.
 
-### `cacheExchange` (Exchange)
+### cacheExchange (Exchange)
 
-The `cacheExchange` as [described in the Basics section](basics.md#cacheexchange).
+The `cacheExchange` as [described in the Basics section](https://formidable.com/open-source/urql/docs/basics#cacheexchange).
 It's of type `Exchange`.
 
-### `subscriptionExchange` (Exchange factory)
+### subscriptionExchange (Exchange factory)
 
-The `subscriptionExchange` as [described in the Basics section](basics.md#subscriptions).
+The `subscriptionExchange` as [described in the Basics section](https://formidable.com/open-source/urql/docs/basics#subscriptions).
 It's of type `Options => Exchange`.
 
 It accepts a single input: `{ forwardSubscription }`. This is a function that
 receives an enriched operation and must return an Observable-like object that
 streams `GraphQLResult`s with `data` and `errors`.
 
-### `ssrExchange` (Exchange factory)
+### ssrExchange (Exchange factory)
 
-The `ssrExchange` as [described in the Basics section](basics.md#server-side-rendering).
+The `ssrExchange` as [described in the Basics section](https://formidable.com/open-source/urql/docs/basics#server-side-rendering).
 It's of type `Options => Exchange`.
 
 It accepts two inputs, `initialState` which is completely
@@ -456,39 +463,39 @@ Basically, the `ssrExchange` is a small cache that collects data
 during the server-side rendering pass, and allows you to populate
 the cache on the client-side with the same data.
 
-During React rehydration this cache will be emptied,
-becomes inactive, and won't change the results of queries after
+During React rehydration this cache will be emptied and it will
+become inactive and won't change the results of queries after
 rehydration.
 
 It needs to be used _after_ other caching Exchanges like the
 `cacheExchange`, but before any _asynchronous_ Exchange like
 the `fetchExchange`.
 
-### `debugExchange` (Exchange)
+### debugExchange (Exchange)
 
 An exchange that writes incoming `Operation`s to `console.log` and
 writes completed `OperationResult`s to `console.log`.
 
-### `dedupExchange` (Exchange)
+### dedupExchange (Exchange)
 
 An exchange that keeps track of ongoing `Operation`s that haven't returned had
 a corresponding `OperationResult` yet. Any duplicate `Operation` that it
 receives is filtered out if the same `Operation` has already been received
 and is still waiting for a result.
 
-### `fallbackExchangeIO` (ExchangeIO)
+### fallbackExchangeIO (ExchangeIO)
 
 This is an `ExchangeIO` function that the `Client` adds on after all
 exchanges. This function is responsible from filtering `teardown` operations
 out of the output and also warns you of unhandled `operationName`s which
 can occur when a subscription is used without adding a `subscriptionExchange`.
 
-### `fetchExchange` (Exchange)
+### fetchExchange (Exchange)
 
-The `fetchExchange` as [described in the Basics section](basics.md#fetchexchange).
+The `fetchExchange` as [described in the Basics section](https://formidable.com/open-source/urql/docs/basics#fetchexchange).
 It's of type `Exchange`.
 
-### `defaultExchanges` (Exchange[])
+### defaultExchanges (Exchange[])
 
 An array of the default exchanges that the `Client` uses when it wasn't passed
 an `exchanges` option.
diff --git a/docs/architecture.md b/docs/architecture.md
index f2fe79ad..e16d0e55 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -1,3 +1,10 @@
+---
+title: architecture
+order: 1
+---
+
+<a name="architecture"></a>
+
 # Architecture
 
 Much of `urql` is about being flexible and customizable.
diff --git a/docs/basics.md b/docs/basics.md
index e280af68..3db80cbf 100644
--- a/docs/basics.md
+++ b/docs/basics.md
@@ -1,5 +1,14 @@
+---
+title: Basics
+order: 2
+---
+
+<a name="basics"></a>
+
 # Basics
 
+<a name="main-file"></a>
+
 As mentioned before, `urql`'s core logic is split into exchanges.
 To that end, `urql`'s behavior is completely defined by the exchanges
 you pass to it or that are the default ones.
@@ -21,7 +30,9 @@ const client = new Client({
 This list of default exchanges is also exported as `defaultExchanges`
 however.
 
-## `fetchExchange`
+## fetchExchange
+
+<a name="fetchexchange"></a>
 
 The `fetchExchange` handles `query` and `mutation` operations and uses `fetch`
 to send GraphQL API requests.
@@ -63,7 +74,9 @@ allow `response.status >= 300` when `redirect` is set to `'manual'`.
 **In summary:** `fetchExchange` is a simple request handler that takes
 operations and sends `POST` requests using `fetch`.
 
-## `cacheExchange`
+## cacheExchange
+
+<a name="cacheexchange"></a>
 
 The default caching behavior that `urql` uses is defined by the `cacheExchange`
 unlike Apollo's `Cache` or `InMemoryCache`, caching behavior is handled as
@@ -113,7 +126,7 @@ respond with the types that are invalidated.
 Given an `addTodo` mutation for example, you will need to send
 back at least one `TodoItem` for the invalidation to happen.
 
-A **document cache** also doesn't normalise at all, which means
+A **document cache** also doesn't normalize at all, which means
 that after fetching a list of items, fetching a single item
 will never be fulfilled by this cache.
 
@@ -152,10 +165,10 @@ from the API.
 
 ### Customization
 
-The idea of `urql` is that you can customise the caching behavior amongst
+The idea of `urql` is that you can customize the caching behavior amongst
 other things yourself, if needed.
 
-[Read more about customising `urql` in the "Extending & Experimenting" section.](extending-and-experimenting.md)
+[Read more about customizing `urql` in the "Extending & Experimenting" section.](https://formidable.com/open-source/urql/docs/extending-&-experimenting)
 
 ## Server-side rendering
 
@@ -180,7 +193,7 @@ it to prefetch data on the server-side. For this reason we have a companion
 library, [`react-ssr-prepass`](https://github.com/FormidableLabs/react-ssr-prepass), which can be used to run a "prepass"
 that fetches all suspended data it finds in a React element tree.
 
-### Setting up the `Client`
+### Setting up the Client
 
 When you set up the `Client` for server-side rendering, on the server
 you will need to set `suspense` to `true` and on the client to `false`,
@@ -328,7 +341,7 @@ up [have a look at our SSR + next.js example project](https://github.com/Formida
 ## Subscriptions
 
 One feature of `urql` that was not mentioned in the
-["Getting Started" section](getting-started.md) is `urql`'s
+["Getting Started" section](https://formidable.com/open-source/urql/docs/getting-started) is `urql`'s
 APIs and ability to handle subscriptions.
 
 To add support for subscriptions there's the `subscriptionExchange`.
diff --git a/docs/exchanges.md b/docs/exchanges.md
index 584d1f83..37e33b23 100644
--- a/docs/exchanges.md
+++ b/docs/exchanges.md
@@ -1,3 +1,10 @@
+---
+title: Exchanges
+order: 3
+---
+
+<a name="exchanges"></a>
+
 # Exchanges
 
 ## Packages
diff --git a/docs/extending-and-experimenting.md b/docs/extending-and-experimenting.md
index 83b045d9..89e152b4 100644
--- a/docs/extending-and-experimenting.md
+++ b/docs/extending-and-experimenting.md
@@ -1,7 +1,14 @@
+---
+title: extending-&-experimenting
+order: 4
+---
+
+<a name="extending-&-experimenting"></a>
+
 # Extending & Experimenting
 
-Hopefully you have read the sections on `urql`'s [Architecture](architecture.md)
-and its [Basics](basics.md). This section will introduce you to hacking
+Hopefully you have read the sections on `urql`'s [Architecture](https://formidable.com/open-source/urql/docs/architecture)
+and its [Basics](https://formidable.com/open-source/urql/docs/basics). This section will introduce you to hacking
 with `urql`.
 
 `urql` comes with some very functional defaults, but its standard component APIs,
@@ -19,8 +26,7 @@ and hooks or even React at all.
 
 The Client is structured so that it can easily be reused to create different
 APIs or integrate `urql` with other libraries and frameworks than React.
-[Have a look at the API docs to see a full list of the client's methods.](api.md#client-class)
-Also take a look at [how to use `urql` outside of a React context.](url-outside-react.md)
+[Have a look at the API docs to see a full list of the client's methods.](https://formidable.com/open-source/urql/docs/api#client-class)
 
 While it's possible to write new APIs outside of React or new components
 quite easily, this section will only focus on hooks, for illustrative
diff --git a/docs/getting-started.md b/docs/getting-started.md
index fc411247..9de7598a 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -1,3 +1,10 @@
+---
+title: Getting Started
+order: 0
+---
+
+<a name="getting-started"></a>
+
 # Getting Started
 
 ## Installation
@@ -109,7 +116,7 @@ is not the plural `errors`. `urql` wraps any network error or GraphQL
 errors in a `CombinedError` which is more convenient to handle and
 observe.
 
-[Read more about the result's API in the Architecture's Results section.](architecture.md#operation-results)
+[Read more about the result's API in the Architecture's Results section.](https://formidable.com/open-source/urql/docs/architecture#operation-results)
 
 ### Using hooks
 
@@ -162,16 +169,16 @@ as soon as it's mounted and will rerun it when the query or variables change.
 > A tutorial on the `useQuery` hook is also available as a
 > [screencast on egghead](https://egghead.io/lessons/graphql-query-graphql-data-with-urql-using-react-hooks?pl=introduction-to-urql-a-react-graphql-client-faaa2bf5).
 
-[Read more about the result's API in the Architecture's Results section.](architecture.md#operation-results)
+[Read more about the result's API in the Architecture's Results section.](https://formidable.com/open-source/urql/docs/architecture#operation-results)
 
-### Using `graphql-tag`
+### Using graphql-tag
 
 You're not limited to just passing in strings as queries. You can also
 pass in a fully parsed AST in the form of `DocumentNode` instead.
 For this purpose you can use `graphql-tag`.
 
 This can be extremely helpful, since it enables syntax highlighting
-in some editors. It also can be used to pre-parse the GraphQL query
+in some editors. It also can be used to preparse the GraphQL query
 using `babel-plugin-graphql-tag` or the included Webpack loader.
 
 You only have to make a small adjustment. Install `graphql-tag` and
@@ -353,7 +360,7 @@ cached completely. When the same query and variables are requested again,
 result is also invalidated when a mutation with similar `__typename`s was
 sent.
 
-[You can find out more about the default caching behavior in the Basics' `cacheExchange` section.](basics.md#cacheexchange)
+[You can find out more about the default caching behavior in the Basics' `cacheExchange` section.](https://formidable.com/open-source/urql/docs/basics#cacheexchange)
 
 Using `urql`'s default behavior this means we sometimes need a way to refetch
 data from the GraphQL API and skip the cache, if we need fresh data.
@@ -382,15 +389,15 @@ Including `'cache-and-network'` there are four request policies in total:
 - `cache-and-network`: As stated above, this returns the cached result and then also
   sends a request to the API.
 
-[You can find out more about how the default cache behaves when it receives these request policies in the Basics' `cacheExchange` section.](basics.md#request-policies)
+[You can find out more about how the default cache behaves when it receives these request policies in the Basics' `cacheExchange` section.](https://formidable.com/open-source/urql/docs/basics#request-policies)
 
 Next, we can take a look at how to use `'network-only'` to force a refetch
 imperatively. In our previous example this would come in handy to refresh the
 list of todos.
 
 ```jsx
-import React from 'react';
-import { Query } from 'urql';
+import React from "react";
+import { Query } from "urql";
 
 const getTodos = `
   query GetTodos {
@@ -402,7 +409,7 @@ const getTodos = `
   }
 `;
 
-const TodoList = () => {
+const TodoList = () => (
   <Query query={getTodos}>
     {({ executeQuery, data }) => {
       if (!data) {
@@ -426,7 +433,7 @@ const TodoList = () => {
       );
     }}
   </Query>;
-};
+);
 ```
 
 As can be seen, the `<Query>` render props also expose an `executeQuery` method, which
diff --git a/docs/guides.md b/docs/guides.md
index 43e283ed..2519428d 100644
--- a/docs/guides.md
+++ b/docs/guides.md
@@ -1,3 +1,10 @@
+---
+title: guides
+order: 4
+---
+
+<a name="guides"></a>
+
 # Guides
 
 In `urql`, all queries and requests start as "operations". A stream
@@ -9,7 +16,7 @@ They're not unlike middleware in an HTTP server implementation like
 Express. They have the ability to forward operations to the next
 exchange and to return the stream of results from the next exchange.
 
-[You can read more about this structure in our "Architecture" section](./architecture.md)
+[You can read more about this structure in our "Architecture" section](https://formidable.com/open-source/urql/docs/architecture)
 
 These guides are not intended as best practices or specific instructions for
 writing exchanges. Rather they teach you how to get started on creating
@@ -81,7 +88,7 @@ const noopExchange = ({ client, forward }) => {
 };
 ```
 
-In this form it doesn't do anything yet.
+In this form the exchange doesn't do anything yet.
 When you create a client and pass it an array of exchanges, all exchanges
 will be composed together into a single one. They will each be called with
 an object that contains the `client` itself, and a `forward` function which
diff --git a/docs/urql-outside-react.md b/docs/urql-outside-react.md
index 31e841ce..770b943e 100644
--- a/docs/urql-outside-react.md
+++ b/docs/urql-outside-react.md
@@ -1,4 +1,11 @@
-# `urql` Outside of React
+---
+title: urql outside of react
+order: 5
+---
+
+<a name="urql-outside-of-react"></a>
+
+# urql Outside of React
 
 While `urql` is a GraphQL client that's mainly targeting React, apart from our React-specific APIs (i.e. the hooks and components), all other elements of the library function the same outside of a React context. In this guide, we'll take a look at using `urql` in environments other than React, including NodeJS and Vue.
 
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index f7c86247..58b57faa 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -1,4 +1,3 @@
 export * from './useMutation';
 export * from './useQuery';
 export * from './useSubscription';
-export * from './useDevtoolsContext';
diff --git a/src/hooks/useDevtoolsContext.ts b/src/hooks/useDevtoolsContext.ts
deleted file mode 100644
index dc257953..00000000
--- a/src/hooks/useDevtoolsContext.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import * as React from 'react';
-import { OperationContext } from '../types';
-
-const {
-  ReactCurrentOwner: CurrentOwner,
-} = (React as any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
-
-// Is the Fiber a FunctionComponent, ClassComponent, or IndeterminateComponent
-const isComponentFiber = (fiber: void | { tag: number }) =>
-  fiber && (fiber.tag === 0 || fiber.tag === 1 || fiber.tag === 2);
-
-// Is the component one of ours (just a heuristic to avoid circular dependencies or flags)
-const isInternalComponent = (Component: { name: string }) =>
-  Component.name === 'Query' ||
-  Component.name === 'Mutation' ||
-  Component.name === 'Subscription';
-
-const useDevtoolsContextImpl = (): Partial<OperationContext> => {
-  return React.useMemo(() => {
-    let source = 'Component';
-
-    // Check whether the CurrentOwner is set
-    const owner = CurrentOwner.current;
-    if (owner !== null && isComponentFiber(owner)) {
-      let Component = owner.type;
-
-      // If this is one of our own components then check the parent
-      if (
-        isInternalComponent(Component) &&
-        isComponentFiber(owner._debugOwner)
-      ) {
-        Component = owner._debugOwner.type;
-      }
-
-      // Get the Component's name if it has one
-      if (typeof Component === 'function') {
-        source = Component.displayName || Component.name || source;
-      }
-    }
-
-    return { meta: { source } };
-  }, []);
-};
-
-/** Creates additional context values for serving metadata to devtools. */
-export const useDevtoolsContext: () => Partial<OperationContext> | undefined =
-  // NOTE: We check for CurrentOwner in case it'll be unexpectedly changed in React's source
-  process.env.NODE_ENV !== 'production' && !!CurrentOwner
-    ? useDevtoolsContextImpl
-    : () => undefined;
diff --git a/src/hooks/useMutation.ts b/src/hooks/useMutation.ts
index 63f2abea..b4c83cb7 100644
--- a/src/hooks/useMutation.ts
+++ b/src/hooks/useMutation.ts
@@ -5,7 +5,6 @@ import { Context } from '../context';
 import { OperationResult, OperationContext } from '../types';
 import { CombinedError, createRequest } from '../utils';
 import { useImmediateState } from './useImmediateState';
-import { useDevtoolsContext } from './useDevtoolsContext';
 
 export interface UseMutationState<T> {
   fetching: boolean;
@@ -22,7 +21,6 @@ export type UseMutationResponse<T, V> = [
 export const useMutation = <T = any, V = object>(
   query: DocumentNode | string
 ): UseMutationResponse<T, V> => {
-  const devtoolsContext = useDevtoolsContext();
   const client = useContext(Context);
   const [state, setState] = useImmediateState<UseMutationState<T>>({
     fetching: false,
@@ -43,7 +41,7 @@ export const useMutation = <T = any, V = object>(
       const request = createRequest(query, variables as any);
 
       return pipe(
-        client.executeMutation(request, { ...devtoolsContext, ...context }),
+        client.executeMutation(request, context || {}),
         toPromise
       ).then(result => {
         const { data, error, extensions } = result;
@@ -51,7 +49,7 @@ export const useMutation = <T = any, V = object>(
         return result;
       });
     },
-    [client, devtoolsContext, query, setState]
+    [client, query, setState]
   );
 
   return [state, executeMutation];
diff --git a/src/hooks/useQuery.spec.ts b/src/hooks/useQuery.spec.ts
index 8236254d..00f3442e 100644
--- a/src/hooks/useQuery.spec.ts
+++ b/src/hooks/useQuery.spec.ts
@@ -80,7 +80,6 @@ describe('useQuery', () => {
         variables: mockVariables,
       },
       {
-        meta: { source: 'TestHook' },
         requestPolicy: undefined,
         url: 'test',
       }
diff --git a/src/hooks/useQuery.ts b/src/hooks/useQuery.ts
index ddd80b4e..03bb45dd 100644
--- a/src/hooks/useQuery.ts
+++ b/src/hooks/useQuery.ts
@@ -4,7 +4,6 @@ import { pipe, subscribe } from 'wonka';
 import { Context } from '../context';
 import { OperationContext, RequestPolicy } from '../types';
 import { CombinedError, noop } from '../utils';
-import { useDevtoolsContext } from './useDevtoolsContext';
 import { useRequest } from './useRequest';
 import { useImmediateEffect } from './useImmediateEffect';
 import { useImmediateState } from './useImmediateState';
@@ -33,7 +32,6 @@ export type UseQueryResponse<T> = [
 export const useQuery = <T = any, V = object>(
   args: UseQueryArgs<V>
 ): UseQueryResponse<T> => {
-  const devtoolsContext = useDevtoolsContext();
   const unsubscribe = useRef(noop);
   const client = useContext(Context);
 
@@ -62,7 +60,6 @@ export const useQuery = <T = any, V = object>(
           pollInterval: args.pollInterval,
           ...args.context,
           ...opts,
-          ...devtoolsContext,
         }),
         subscribe(({ data, error, extensions }) => {
           setState({ fetching: false, data, error, extensions });
@@ -74,7 +71,6 @@ export const useQuery = <T = any, V = object>(
       args.requestPolicy,
       args.pollInterval,
       client,
-      devtoolsContext,
       request,
       setState,
     ]
diff --git a/src/hooks/useSubscription.ts b/src/hooks/useSubscription.ts
index 25ea6843..8562c414 100644
--- a/src/hooks/useSubscription.ts
+++ b/src/hooks/useSubscription.ts
@@ -3,7 +3,6 @@ import { useCallback, useContext, useEffect, useRef } from 'react';
 import { pipe, subscribe } from 'wonka';
 import { Context } from '../context';
 import { CombinedError, noop } from '../utils';
-import { useDevtoolsContext } from './useDevtoolsContext';
 import { useRequest } from './useRequest';
 import { useImmediateState } from './useImmediateState';
 import { OperationContext } from '../types';
@@ -29,7 +28,6 @@ export const useSubscription = <T = any, R = T, V = object>(
   args: UseSubscriptionArgs<V>,
   handler?: SubscriptionHandler<T, R>
 ): UseSubscriptionResponse<R> => {
-  const devtoolsContext = useDevtoolsContext();
   const unsubscribe = useRef(noop);
   const client = useContext(Context);
 
@@ -48,10 +46,7 @@ export const useSubscription = <T = any, R = T, V = object>(
     unsubscribe.current();
 
     [unsubscribe.current] = pipe(
-      client.executeSubscription(request, {
-        ...devtoolsContext,
-        ...args.context,
-      }),
+      client.executeSubscription(request, args.context || {}),
       subscribe(({ data, error, extensions }) => {
         setState(s => ({
           fetching: true,
@@ -61,7 +56,7 @@ export const useSubscription = <T = any, R = T, V = object>(
         }));
       })
     );
-  }, [client, devtoolsContext, handler, request, setState, args.context]);
+  }, [client, handler, request, setState, args.context]);
 
   // Trigger subscription on query change
   // We don't use useImmediateEffect here as we have no way of
diff --git a/src/utils/typenames.ts b/src/utils/typenames.ts
index d4979b5b..6fde1d11 100755
--- a/src/utils/typenames.ts
+++ b/src/utils/typenames.ts
@@ -2,7 +2,7 @@ import {
   DocumentNode,
   FieldNode,
   InlineFragmentNode,
-  OperationDefinitionNode,
+  Kind,
   visit,
 } from 'graphql';
 
@@ -35,9 +35,7 @@ const collectTypes = (obj: EntityLike | EntityLike[], types: string[] = []) => {
 export const collectTypesFromResponse = (response: object) =>
   collectTypes(response as EntityLike).filter((v, i, a) => a.indexOf(v) === i);
 
-const formatNode = (
-  n: FieldNode | InlineFragmentNode | OperationDefinitionNode
-) => {
+const formatNode = (n: FieldNode | InlineFragmentNode) => {
   if (n.selectionSet === undefined) {
     return false;
   }
@@ -57,9 +55,9 @@ const formatNode = (
       selections: [
         ...n.selectionSet.selections,
         {
-          kind: 'Field',
+          kind: Kind.FIELD,
           name: {
-            kind: 'Name',
+            kind: Kind.NAME,
             value: '__typename',
           },
         },
@@ -72,5 +70,4 @@ export const formatDocument = (astNode: DocumentNode) =>
   visit(astNode, {
     Field: formatNode,
     InlineFragment: formatNode,
-    OperationDefinition: formatNode,
   });


Test patch:
diff --git a/src/hooks/useDevtoolsContext.test.ts b/src/hooks/useDevtoolsContext.test.ts
deleted file mode 100644
index 6d2eebca..00000000
--- a/src/hooks/useDevtoolsContext.test.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-import React, { Component } from 'react';
-import renderer from 'react-test-renderer';
-import { useDevtoolsContext } from './useDevtoolsContext';
-
-it('retrieves the component name for function components', () => {
-  let hookResult;
-
-  const TestFunComponent = () => {
-    hookResult = useDevtoolsContext();
-    return null;
-  };
-
-  renderer.create(React.createElement(TestFunComponent));
-
-  expect(hookResult).toEqual({
-    meta: {
-      source: 'TestFunComponent',
-    },
-  });
-});
-
-it('prefers displayNames', () => {
-  let hookResult;
-
-  const TestFunComponent = () => {
-    hookResult = useDevtoolsContext();
-    return null;
-  };
-
-  TestFunComponent.displayName = 'TestFun';
-
-  renderer.create(React.createElement(TestFunComponent));
-
-  expect(hookResult).toEqual({
-    meta: {
-      source: 'TestFun',
-    },
-  });
-});
-
-it('retrieves the component name for function components using Query', () => {
-  let hookResult;
-
-  // We're not using the actual query component here but one with the _same name_
-  const Query = () => {
-    hookResult = useDevtoolsContext();
-    return null;
-  };
-
-  const OuterFunComponent = () => {
-    return React.createElement(Query);
-  };
-
-  renderer.create(React.createElement(OuterFunComponent));
-
-  expect(hookResult).toEqual({
-    meta: {
-      source: 'OuterFunComponent',
-    },
-  });
-});
-
-it('retrieves the component name for class components using Query', () => {
-  let hookResult;
-
-  // We're not using the actual query component here but one with the _same name_
-  const Query = () => {
-    hookResult = useDevtoolsContext();
-    return null;
-  };
-
-  class OuterClassComponent extends Component {
-    render() {
-      return React.createElement(Query);
-    }
-  }
-
-  renderer.create(React.createElement(OuterClassComponent));
-
-  expect(hookResult).toEqual({
-    meta: {
-      source: 'OuterClassComponent',
-    },
-  });
-});
-
-it('looks at the parent component, not the parent fiber', () => {
-  let hookResult;
-
-  // A context consumer/provider has a different Fiber type
-  const TestContext = React.createContext('');
-
-  // We're not using the actual query component here but one with the _same name_
-  const Query = () => {
-    hookResult = useDevtoolsContext();
-    return null;
-  };
-
-  class OuterClassComponent extends Component {
-    render() {
-      // Basically put one element "in the middle" of OuterClassComponent and Query
-      return React.createElement(
-        TestContext.Provider,
-        { value: 'test' },
-        React.createElement(Query)
-      );
-    }
-  }
-
-  renderer.create(React.createElement(OuterClassComponent));
-
-  expect(hookResult).toEqual({
-    meta: {
-      source: 'OuterClassComponent',
-    },
-  });
-});
diff --git a/src/hooks/useMutation.test.tsx b/src/hooks/useMutation.test.tsx
index 235add9d..f6732d85 100644
--- a/src/hooks/useMutation.test.tsx
+++ b/src/hooks/useMutation.test.tsx
@@ -107,16 +107,6 @@ describe('on execute', () => {
     );
   });
 
-  it('calls executeMutation with source component info', () => {
-    renderer.create(<MutationUser {...props} />);
-    act(() => {
-      execute(vars);
-    });
-    expect(client.executeMutation.mock.calls[0][1]).toHaveProperty('meta', {
-      source: 'MutationUser',
-    });
-  });
-
   it('can adjust context in executeMutation', () => {
     renderer.create(<MutationUser {...props} />);
     act(() => {
diff --git a/src/hooks/useQuery.test.tsx b/src/hooks/useQuery.test.tsx
index cd03726b..2740be19 100644
--- a/src/hooks/useQuery.test.tsx
+++ b/src/hooks/useQuery.test.tsx
@@ -88,19 +88,6 @@ describe('on initial useEffect', () => {
       })
     );
   });
-
-  it('passes source component name to executeQuery', () => {
-    renderer.create(<QueryUser {...props} />);
-
-    expect(client.executeQuery).toBeCalledWith(
-      expect.any(Object),
-      expect.objectContaining({
-        meta: {
-          source: 'QueryUser',
-        },
-      })
-    );
-  });
 });
 
 describe('on subscription', () => {
diff --git a/src/hooks/useSubscription.test.tsx b/src/hooks/useSubscription.test.tsx
index 6d043069..2a1db21f 100644
--- a/src/hooks/useSubscription.test.tsx
+++ b/src/hooks/useSubscription.test.tsx
@@ -62,14 +62,6 @@ describe('on initial useEffect', () => {
       expect.any(Object)
     );
   });
-
-  it('passes source component info to executeSubscription', () => {
-    renderer.create(<SubscriptionUser q={query} />);
-    expect(client.executeSubscription).toBeCalledWith(
-      expect.any(Object),
-      expect.objectContaining({ meta: { source: 'SubscriptionUser' } })
-    );
-  });
 });
 
 it('should support setting context in useSubscription params', () => {
@@ -85,7 +77,6 @@ it('should support setting context in useSubscription params', () => {
     },
     {
       url: 'test',
-      meta: { source: 'SubscriptionUser' },
     }
   );
 });
diff --git a/src/utils/typenames.test.ts b/src/utils/typenames.test.ts
index aadf1403..48a10591 100755
--- a/src/utils/typenames.test.ts
+++ b/src/utils/typenames.test.ts
@@ -14,7 +14,6 @@ describe('formatTypeNames', () => {
           id
           __typename
         }
-        __typename
       }
       "
     `);
@@ -29,15 +28,15 @@ describe('formatTypeNames', () => {
       __typename
     }`)
     ).toMatchInlineSnapshot(`
-            "{
-              todos {
-                id
-                __typename
-              }
-              __typename
-            }
-            "
-        `);
+                  "{
+                    todos {
+                      id
+                      __typename
+                    }
+                    __typename
+                  }
+                  "
+            `);
   });
 });