@@ -156,6 +156,8 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
156156 _storage : StorageAPI ;
157157
158158 codeMirrorSizer ! : CodeMirrorSizer ;
159+ // Ensure the component is mounted to execute async setState
160+ componentIsMounted : boolean ;
159161
160162 // refs
161163 docExplorerComponent : Maybe < DocExplorer > ;
@@ -178,6 +180,9 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
178180 // Cache the storage instance
179181 this . _storage = new StorageAPI ( props . storage ) ;
180182
183+ // Disable setState when the component is not mounted
184+ this . componentIsMounted = false ;
185+
181186 // Determine the initial query to display.
182187 const query =
183188 props . query !== undefined
@@ -251,6 +256,9 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
251256 }
252257
253258 componentDidMount ( ) {
259+ // Allow async state changes
260+ this . componentIsMounted = true ;
261+
254262 // Only fetch schema via introspection if a schema has not been
255263 // provided, including if `null` was provided.
256264 if ( this . state . schema === undefined ) {
@@ -349,6 +357,9 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
349357 // When the component is about to unmount, store any persistable state, such
350358 // that when the component is remounted, it will use the last used values.
351359 componentWillUnmount ( ) {
360+ // Deny async state changes
361+ this . componentIsMounted = false ;
362+
352363 if ( this . state . query ) {
353364 this . _storage . set ( 'query' , this . state . query ) ;
354365 }
@@ -377,6 +388,12 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
377388 ) ;
378389 }
379390
391+ // Use it when the state change is async
392+ // TODO: Annotate correctly this function
393+ safeSetState = ( nextState : any , callback ?: any ) : void => {
394+ this . componentIsMounted && this . setState ( nextState , callback ) ;
395+ } ;
396+
380397 render ( ) {
381398 const children = React . Children . toArray ( this . props . children ) ;
382399
@@ -745,19 +762,19 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
745762 if ( typeof result !== 'string' && 'data' in result ) {
746763 const schema = buildClientSchema ( result . data ) ;
747764 const queryFacts = getQueryFacts ( schema , this . state . query ) ;
748- this . setState ( { schema, ...queryFacts } ) ;
765+ this . safeSetState ( { schema, ...queryFacts } ) ;
749766 } else {
750767 const responseString =
751768 typeof result === 'string' ? result : GraphiQL . formatResult ( result ) ;
752- this . setState ( {
769+ this . safeSetState ( {
753770 // Set schema to `null` to explicitly indicate that no schema exists.
754771 schema : undefined ,
755772 response : responseString ,
756773 } ) ;
757774 }
758775 } )
759776 . catch ( error => {
760- this . setState ( {
777+ this . safeSetState ( {
761778 schema : undefined ,
762779 response : error ? GraphiQL . formatError ( error ) : undefined ,
763780 } ) ;
@@ -794,7 +811,7 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
794811 // If fetcher returned a Promise, then call the callback when the promise
795812 // resolves, otherwise handle the error.
796813 fetch . then ( cb ) . catch ( error => {
797- this . setState ( {
814+ this . safeSetState ( {
798815 isWaitingForResponse : false ,
799816 response : error ? GraphiQL . formatError ( error ) : undefined ,
800817 } ) ;
@@ -806,14 +823,14 @@ export class GraphiQL extends React.Component<GraphiQLProps, GraphiQLState> {
806823 const subscription = fetch . subscribe ( {
807824 next : cb ,
808825 error : ( error : Error ) => {
809- this . setState ( {
826+ this . safeSetState ( {
810827 isWaitingForResponse : false ,
811828 response : error ? GraphiQL . formatError ( error ) : undefined ,
812829 subscription : null ,
813830 } ) ;
814831 } ,
815832 complete : ( ) => {
816- this . setState ( {
833+ this . safeSetState ( {
817834 isWaitingForResponse : false ,
818835 subscription : null ,
819836 } ) ;
0 commit comments