Skip to content

Commit 54a68b1

Browse files
Merge pull request #4 from dskelton-r7/feature/timeouts
timeouts
2 parents 2c7dcb6 + ad8b028 commit 54a68b1

File tree

4 files changed

+142
-9
lines changed

4 files changed

+142
-9
lines changed

README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,68 @@ const Example = () => {
3333
</p>
3434
)
3535
}
36+
37+
```
38+
39+
### Aborting a request via custom timeout
40+
41+
```jsx
42+
import useFetch from '@chrislaughlin/usefetch'
43+
44+
const CustomTimeout = () => {
45+
const { isLoading, error, data } = useFetch('https://get.geojs.io/v1/ip/country.json?ip=8.8.8.8', {timeout: 1000});
46+
47+
if (isLoading) {
48+
return <p>Loading.....</p>
49+
}
50+
51+
if (error) {
52+
return <p>{JSON.stringify(error)}</p>
53+
}
54+
55+
return (
56+
<div>
57+
<p>
58+
{JSON.stringify(data)}
59+
</p>
60+
</div>
61+
)
62+
};
63+
```
64+
65+
### Aborting a request via consuming application
66+
67+
```jsx
68+
import useFetch from '@chrislaughlin/usefetch'
69+
70+
const AbortExample = () => {
71+
const { isLoading, error, data, abortController } = useFetch('https://get.geojs.io/v1/ip/country.json?ip=8.8.8.8');
72+
73+
React.useEffect(() => {
74+
const timer = setTimeout(() => {
75+
if (isLoading) {
76+
console.log('aborted after 100ms');
77+
abortController.abort();
78+
}
79+
}, 100);
80+
81+
return () => clearTimeout(timer);
82+
}, [isLoading])
83+
84+
if (isLoading) {
85+
return <p>Loading.....</p>
86+
}
87+
88+
if (error) {
89+
return <p>{JSON.stringify(error)}</p>
90+
}
91+
92+
return (
93+
<div>
94+
<p>
95+
{JSON.stringify(data)}
96+
</p>
97+
</div>
98+
)
99+
};
36100
```

demo/src/examples/aborts.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react';
2+
import useFetch from '../../../src'
3+
4+
const Aborts = () => {
5+
const { isLoading, error, data, abortController } = useFetch('https://get.geojs.io/v1/ip/country.json?ip=8.8.8.8');
6+
7+
React.useEffect(() => {
8+
const timer = setTimeout(() => {
9+
if (isLoading) {
10+
console.log('aborted after 100ms');
11+
abortController.abort();
12+
}
13+
}, 100);
14+
15+
return () => clearTimeout(timer);
16+
}, [isLoading])
17+
18+
if (isLoading) {
19+
return <p>Loading.....</p>
20+
}
21+
22+
if (error) {
23+
return <p>{JSON.stringify(error)}</p>
24+
}
25+
26+
return (
27+
<div>
28+
<p>
29+
{JSON.stringify(data)}
30+
</p>
31+
</div>
32+
)
33+
};
34+
35+
export default Aborts;

demo/src/index.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React from 'react'
22
import {render} from 'react-dom'
3-
43
import useFetch from '../../src'
4+
import Example2 from './examples/aborts';
55

66
const Example = () => {
7-
const { isLoading, error, data} = useFetch('https://get.geojs.io/v1/ip/country.json?ip=8.8.8.8')
7+
const { isLoading, error, data } = useFetch('https://get.geojs.io/v1/ip/country.json?ip=8.8.8.8');
88

99
if (isLoading) {
1010
return <p>Loading.....</p>
@@ -23,4 +23,11 @@ const Example = () => {
2323
)
2424
}
2525

26-
render(<Example/>, document.querySelector('#demo'))
26+
const Examples = () => (
27+
<>
28+
<Example />
29+
<Example2 />
30+
</>
31+
);
32+
33+
render(<Examples />, document.querySelector('#demo'))

src/index.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,56 @@
1-
import { useState, useEffect } from 'react';
1+
import {
2+
useState,
3+
useEffect,
4+
useRef,
5+
} from 'react';
26

37
const useFetch = (url, options) => {
4-
const [isLoading, setIsLoading] = useState(true);
8+
const [isLoading, setIsLoading] = useState(false);
59
const [error, setError] = useState(null);
610
const [data, setData] = useState(null);
11+
const abortControllerRef = useRef();
712

813
useEffect(() => {
9-
fetch(url, options || {})
14+
15+
abortControllerRef.current = new AbortController();
16+
17+
setIsLoading(true);
18+
19+
const fetchOptions = options || {};
20+
21+
let timeout;
22+
23+
if (fetchOptions.timeout) {
24+
timeout = setTimeout(() => abortControllerRef.current.abort(), fetchOptions.timeout);
25+
}
26+
27+
fetch(url, {...fetchOptions, signal: abortControllerRef.current.signal})
1028
.then(res => res.json())
1129
.then(response => {
1230
setData(response);
1331
setIsLoading(false);
1432
setError(null);
1533
})
16-
.catch(error => {
34+
.catch(error => {
1735
setData(null);
1836
setIsLoading(false);
1937
setError(error);
2038
})
21-
}, [url, options])
39+
40+
return () => {
41+
if (timeout) {
42+
clearTimeout(timeout);
43+
}
44+
45+
abortControllerRef.current.abort();
46+
}
47+
}, [url])
2248

2349
return {
2450
isLoading,
2551
error,
26-
data
52+
data,
53+
abortController: abortControllerRef.current,
2754
}
2855
};
2956

0 commit comments

Comments
 (0)