Skip to content

Instantly share code, notes, and snippets.

@christianwish
Last active April 18, 2019 14:28
Show Gist options
  • Save christianwish/d038569998f001f63dd4c9c92c2e0af3 to your computer and use it in GitHub Desktop.
Save christianwish/d038569998f001f63dd4c9c92c2e0af3 to your computer and use it in GitHub Desktop.
Experimental React Custom Hook to prevent "can't perform a React state update on an unmounted component"
import React, { useEffect, useState } from 'react';
import { usePromiseEffect } from './usePromiseEffect';
const ToggleMount = () => {
const [fetched, setFetched] = useState(false);
const callbacks = {
resolve: (res) => {
setFetched(true);
},
unmountedResolve: (res) => {
// something else to do, but no state updates
},
reject: (err) => {
setFetched(true);
},
unmountedReject: (err) => {
// something else to do, but no state updates
},
};
usePromiseEffect(
fetch('http://mycoolApiEndpoint.net'),
callbacks,
[],
);
return <h1>{ fetched ? 'Fetched' : 'Mounted' }</h1>;
};
import { useEffect } from 'react';
const isFn = x => typeof x === 'function';
export const usePromiseEffect = (promise, callbacks, arr) => {
let mounted = true;
const {
resolve,
reject,
unmountedReject,
unmountedResolve,
} = callbacks;
useEffect(() => {
promise
.then((res) => {
if (mounted && isFn(resolve)) {
resolve(res);
return;
}
if (isFn(unmountedResolve)) {
unmountedResolve(res);
}
}).catch((err) => {
if (mounted && isFn(reject)) {
reject(err);
return;
}
if (isFn(unmountedReject)) {
unmountedReject(err);
}
});
return function cleanup() { mounted = false; };
}, arr);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment