Skip to content

Commit

Permalink
Fix react warning (#656)
Browse files Browse the repository at this point in the history
* fix react unmounted warning

* add mounted check to useMutation

* add changeset

* run linter

* add the .js to svelte again

* undo last commit

* add .js for suspense

* remove react peerDep from retry

* fix prepare script
  • Loading branch information
JoviDeCroock authored Mar 22, 2020
1 parent 9d15bc5 commit f2431a1
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-squids-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'urql': patch
---

Avoid setting state on an unmounted component when useMutation is used
3 changes: 1 addition & 2 deletions exchanges/retry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@
"react-dom": "^16.13.0"
},
"peerDependencies": {
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0",
"react": ">= 16.8.0"
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0"
},
"dependencies": {
"@urql/core": ">=1.10.4",
Expand Down
4 changes: 2 additions & 2 deletions exchanges/suspense/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"react",
"suspense"
],
"main": "dist/urql-exchange-suspense",
"module": "dist/urql-exchange-suspense.mjs",
"main": "dist/urql-exchange-suspense.js",
"module": "dist/urql-exchange-suspense.es.js",
"types": "dist/types/index.d.ts",
"source": "src/index.ts",
"exports": {
Expand Down
25 changes: 17 additions & 8 deletions packages/react-urql/src/hooks/useMutation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DocumentNode } from 'graphql';
import { useState, useCallback } from 'react';
import { useState, useCallback, useRef, useEffect } from 'react';
import { pipe, toPromise } from 'wonka';

import {
Expand Down Expand Up @@ -31,6 +31,7 @@ export type UseMutationResponse<T, V> = [
export const useMutation = <T = any, V = object>(
query: DocumentNode | string
): UseMutationResponse<T, V> => {
const isMounted = useRef(true);
const client = useClient();

const [state, setState] = useState<UseMutationState<T>>(initialState);
Expand All @@ -46,18 +47,26 @@ export const useMutation = <T = any, V = object>(
),
toPromise
).then(result => {
setState({
fetching: false,
stale: !!result.stale,
data: result.data,
error: result.error,
extensions: result.extensions,
});
if (isMounted.current) {
setState({
fetching: false,
stale: !!result.stale,
data: result.data,
error: result.error,
extensions: result.extensions,
});
}
return result;
});
},
[client, query, setState]
);

useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);

return [state, executeMutation];
};
12 changes: 10 additions & 2 deletions packages/react-urql/src/hooks/useSource.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable react-hooks/exhaustive-deps */

import { useMemo, useEffect, useState } from 'react';
import { useMemo, useEffect, useState, useRef } from 'react';

import {
Source,
Expand All @@ -19,6 +19,8 @@ import { useClient } from '../context';
let currentInit = false;

export const useSource = <T>(source: Source<T>, init: T): T => {
const isMounted = useRef(true);

const [state, setState] = useState(() => {
currentInit = true;
let initialValue = init;
Expand All @@ -35,11 +37,17 @@ export const useSource = <T>(source: Source<T>, init: T): T => {
return initialValue;
});

useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);

useEffect(() => {
return pipe(
source,
subscribe(value => {
if (!currentInit) {
if (!currentInit && isMounted.current) {
setState(value);
}
})
Expand Down
2 changes: 1 addition & 1 deletion scripts/prepare/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ if (hasReact) {

invariant(
path.normalize(pkg.module) === `dist/${name}.es.js`,
'package.json:main path must end in `.es.js` for packages depending on React.'
'package.json:module path must end in `.es.js` for packages depending on React.'
);
} else {
invariant(
Expand Down

0 comments on commit f2431a1

Please sign in to comment.