Skip to content

Commit

Permalink
Merge pull request #11 from joeydebreuk/add_abort_fetch_on_unmount
Browse files Browse the repository at this point in the history
Add abort on unmount to get rid of potential memory leak
  • Loading branch information
Espen Henriksen committed May 31, 2020
2 parents 380d74a + 33210fb commit 3445c68
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
25 changes: 25 additions & 0 deletions src/hoc.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const Component = buildComponent(exampleUrl);

const fakeConsoleError = jest.fn(console.error);
const fakeText = jest.fn(() => Promise.resolve('mockText'));
const fakeAbort = jest.fn(() => {});

// Used to check for response.clone()
const clonedFetch = () =>
Expand All @@ -25,6 +26,10 @@ const fakeFetch = () =>
text: fakeText,
clone: fakeClone,
});
class FakeAbortController {
signal = { aborted: false, onabort: null };
abort = fakeAbort;
}

const onCompletion = test =>
new Promise((resolve, reject) => {
Expand Down Expand Up @@ -306,4 +311,24 @@ describe('FetchHOC', () => {
});
})
});

describe('when component unmounts while fetching', () => {
const delay = time => new Promise(res => setTimeout(res, time));
beforeAll(() => {
window.AbortController = FakeAbortController;
// Make sure the fetch doesnt resolve instantly...
window.fetch = jest.fn(async () => {
await delay(100);
return Promise.resolve({});
});
});

it('should abort request', async () => {
const originalAbortController = window.AbortController;
const component = mount(<Component />);
component.unmount();
window.AbortController = originalAbortController;
await onCompletion(() => expect(fakeAbort).toHaveBeenCalledTimes(1));
});
});
});
14 changes: 13 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default (
): Function => Component =>
class FetchHOC extends React.Component {
_isMounted: boolean;
_abortFetch = () => {};

getUrl = () => {
let url = resource;
Expand Down Expand Up @@ -39,9 +40,19 @@ export default (

componentWillUnmount() {
this._isMounted = false;
this._abortFetch();
}

refetchData = () => {
createSignal = () => {
if (!window.AbortController) { return; }
const controller = new window.AbortController();
this._abortFetch = () => {
if (this.state.loading) { controller.abort(); }
};
return controller.signal;
};

refetchData = () => {
this.fetchData(this.getUrl());
};

Expand All @@ -58,6 +69,7 @@ export default (

const init = {
credentials: 'same-origin',
signal: this.createSignal(),
...(typeof options === 'function' ? options(this.props) : options),
};

Expand Down

0 comments on commit 3445c68

Please sign in to comment.