From 8c9b85e2b28afad609f81bb47aecd65d1f1a5a1a Mon Sep 17 00:00:00 2001 From: Thomas Heyenbrock Date: Mon, 14 Nov 2022 15:30:17 +0100 Subject: [PATCH 1/4] show multipart requests as running until they are finished or cancelled --- .changeset/rich-humans-rescue.md | 7 +++++++ packages/graphiql-react/src/execution.tsx | 16 ++++++++++++---- .../graphiql-react/src/toolbar/execute.tsx | 18 ++++++++++-------- 3 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 .changeset/rich-humans-rescue.md diff --git a/.changeset/rich-humans-rescue.md b/.changeset/rich-humans-rescue.md new file mode 100644 index 00000000000..570e945fb3f --- /dev/null +++ b/.changeset/rich-humans-rescue.md @@ -0,0 +1,7 @@ +--- +'@graphiql/react': minor +--- + +Clearly separate between the fetching and subscription state for multipart +requests (like subscriptions) and show the stop-button as long as the +subscription is running diff --git a/packages/graphiql-react/src/execution.tsx b/packages/graphiql-react/src/execution.tsx index 3a466a54164..183b3dec786 100644 --- a/packages/graphiql-react/src/execution.tsx +++ b/packages/graphiql-react/src/execution.tsx @@ -19,11 +19,17 @@ import { createContextHook, createNullableContext } from './utility/context'; export type ExecutionContextType = { /** - * If there is currently a GraphQL request in-flight. For long-running - * requests like subscriptions this will be `true` until the request is - * stopped manually. + * If there is currently a GraphQL request in-flight. For multi-part + * requests like subscriptions this will be `true` while fetching the + * first partial response and `false` while fetching subsequent batches. */ isFetching: boolean; + /** + * If there is currently a GraphQL request in-flight. For multi-part + * requests like subscriptions this will be `true` until the last batch + * has been fetched or the connection is closed from the client. + */ + isSubscribed: boolean; /** * The operation name that will be sent with all GraphQL requests. */ @@ -315,14 +321,16 @@ export function ExecutionContextProvider(props: ExecutionContextProviderProps) { variableEditor, ]); + const isSubscribed = Boolean(subscription); const value = useMemo( () => ({ isFetching, + isSubscribed, operationName: props.operationName ?? null, run, stop, }), - [isFetching, props.operationName, run, stop], + [isFetching, isSubscribed, props.operationName, run, stop], ); return ( diff --git a/packages/graphiql-react/src/toolbar/execute.tsx b/packages/graphiql-react/src/toolbar/execute.tsx index 240fdd18a2a..40cb3b4479f 100644 --- a/packages/graphiql-react/src/toolbar/execute.tsx +++ b/packages/graphiql-react/src/toolbar/execute.tsx @@ -10,23 +10,25 @@ export function ExecuteButton() { nonNull: true, caller: ExecuteButton, }); - const { isFetching, operationName, run, stop } = useExecutionContext({ - nonNull: true, - caller: ExecuteButton, - }); + const { isFetching, isSubscribed, operationName, run, stop } = + useExecutionContext({ + nonNull: true, + caller: ExecuteButton, + }); const operations = queryEditor?.operations || []; const hasOptions = operations.length > 1 && typeof operationName !== 'string'; + const isRunning = isFetching || isSubscribed; - const label = `${isFetching ? 'Stop' : 'Execute'} query (Ctrl-Enter)`; + const label = `${isRunning ? 'Stop' : 'Execute'} query (Ctrl-Enter)`; const buttonProps = { type: 'button' as const, className: 'graphiql-execute-button', - children: isFetching ? : , + children: isRunning ? : , 'aria-label': label, }; - return hasOptions && !isFetching ? ( + return hasOptions && !isRunning ? ( @@ -63,7 +65,7 @@ export function ExecuteButton() {