Skip to content

Commit 362abf5

Browse files
committed
fix: react app subscription handling
1 parent 7ccdd91 commit 362abf5

File tree

4 files changed

+91
-6
lines changed

4 files changed

+91
-6
lines changed

packages/graphql-playground-react/src/components/Playground.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ export class Playground extends React.PureComponent<Props & DocsState, State> {
425425
}
426426

427427
setRef = (index: number, ref: any) => {
428-
this.graphiqlComponents[index] = ref ? ref.getWrappedInstance() : ref
428+
this.graphiqlComponents[index] = ref ? ref.getWrappedInstance() : ref
429429
}
430430

431431
handleChangeSettings = (settings: string) => {
@@ -974,7 +974,12 @@ export class Playground extends React.PureComponent<Props & DocsState, State> {
974974
this.setValueInSession(session.id, 'subscriptionActive', true)
975975
}
976976

977-
const wsConnection = this.wsConnections[session.id]
977+
let wsConnection = this.wsConnections[session.id]
978+
979+
if (!wsConnection) {
980+
this.setWS(session)
981+
wsConnection = this.wsConnections[session.id]
982+
}
978983

979984
const id = wsConnection.subscribe(graphQLParams, (err, res) => {
980985
const data: any = { data: res, isSubscription: true }

packages/graphql-playground-react/src/components/Playground/Results.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from 'react'
22
import ageOfDate from './util/ageOfDate'
33
import { ResultViewer } from './ResultViewer'
44
import { Response } from '../Playground'
5+
import * as cn from 'classnames'
56

67
export interface Props {
78
disableResize?: boolean
@@ -12,11 +13,14 @@ export interface Props {
1213

1314
export default class Results extends React.Component<Props, {}> {
1415
render() {
16+
const { disableResize } = this.props
17+
const isSubscription = this.props.responses.length > 1
1518
return (
1619
<div
17-
className={
18-
'result-window' + (this.props.disableResize ? ' disableResize' : '')
19-
}
20+
className={cn('result-window', {
21+
disableResize,
22+
isSubscription,
23+
})}
2024
ref={this.props.setRef}
2125
>
2226
<style jsx={true}>{`
@@ -55,6 +59,9 @@ export default class Results extends React.Component<Props, {}> {
5559
bottom: 0;
5660
overflow: auto;
5761
}
62+
.isSubscription .result-viewer-wrapper {
63+
position: relative;
64+
}
5865
`}</style>
5966
{this.props.responses.map(response => (
6067
<div key={response.resultID || String(response.time)}>
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Copyright (c) Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import { parse, typeFromAST } from 'graphql'
10+
11+
/**
12+
* Provided previous "queryFacts", a GraphQL schema, and a query document
13+
* string, return a set of facts about that query useful for GraphiQL features.
14+
*
15+
* If the query cannot be parsed, returns undefined.
16+
*/
17+
export default function getQueryFacts(schema, documentStr): any {
18+
if (!documentStr) {
19+
return
20+
}
21+
22+
let documentAST
23+
try {
24+
documentAST = parse(documentStr)
25+
} catch (e) {
26+
return
27+
}
28+
29+
const variableToType = schema ? collectVariables(schema, documentAST) : null
30+
31+
// Collect operations by their names.
32+
const operations: any[] = []
33+
documentAST.definitions.forEach(def => {
34+
if (def.kind === 'OperationDefinition') {
35+
operations.push(def)
36+
}
37+
})
38+
39+
return { variableToType, operations }
40+
}
41+
42+
/**
43+
* Provided a schema and a document, produces a `variableToType` Object.
44+
*/
45+
export function collectVariables(schema, documentAST) {
46+
const variableToType = Object.create(null)
47+
documentAST.definitions.forEach(definition => {
48+
if (definition.kind === 'OperationDefinition') {
49+
const variableDefinitions = definition.variableDefinitions
50+
if (variableDefinitions) {
51+
variableDefinitions.forEach(({ variable, type }) => {
52+
try {
53+
const inputType = typeFromAST(schema, getDeepType(type))
54+
if (inputType) {
55+
variableToType[variable.name.value] = inputType
56+
}
57+
} catch (e) {
58+
debugger
59+
}
60+
})
61+
}
62+
}
63+
})
64+
return variableToType
65+
}
66+
67+
function getDeepType(type) {
68+
if (type.type) {
69+
return getDeepType(type.type)
70+
}
71+
return type
72+
}

packages/graphql-playground-react/src/components/util.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ export function getEndpointFromEndpointConfig(
2020
if (typeof env === 'string') {
2121
return {
2222
endpoint: env,
23+
subscriptionEndpoint: env.replace(/^http/, 'ws'),
2324
}
2425
} else {
2526
return {
2627
endpoint: env.url,
2728
subscriptionEndpoint: env.subscription
2829
? env.subscription!.url
29-
: undefined,
30+
: env.url.replace(/^http/, 'ws'),
3031
headers: env.headers,
3132
}
3233
}

0 commit comments

Comments
 (0)