Reputation: 6158
I have this custom fetch data hook
function fetchData(currentPage) {
const [error, setError] = useState(null)
const [data, setData] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
async function getData() {
axios.get(`https://${MY_API}${currentPage}`)
.then((res) => setData(res.data))
.catch((err) => setError(err))
.finally(() => setLoading(false))
}
getData()
}, [currentPage])
return { data, error, loading }
}
Which is being used as such:
const { data, error, loading } = fetchData(currentPage)
So whenever the currentPage
changes, the hook is called.
I'm having trouble getting the loading
variable to change to true on changing page, it's always false which makes sense as that's what's being returned at the end of the hook.
How do I deal with resetting loading
to false WITHIN the hook? Or is there another way to deal with this?
Upvotes: 1
Views: 75
Reputation: 3986
In order to simply fix your issue, the loading flag should be set by the effect itself:
function fetchData(currentPage) {
const [error, setError] = useState(null)
const [data, setData] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
setLoading(true);
async function getData() {
axios.get(`https://${MY_API}${currentPage}`)
.then((res) => setData(res.data))
.catch((err) => setError(err))
.finally(() => setLoading(false))
}
getData()
}, [currentPage])
return { data, error, loading }
}
If you want to cancel pending requests and make sure they do not override the fetched data after page changes, you must cancel them out.
The easiest solution would be simply to ignore the response (canceled
flag). However, axios supports cancelation so the proper implementation is not that hard:
function fetchData(currentPage) {
const [error, setError] = useState(null)
const [data, setData] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
let canceled = false;
async function getData() {
axios.get(
`https://${MY_API}${currentPage}`,
{ cancelToken: source.token }
)
.then((res) => setData(res.data))
.catch((err) => {
if (!axios.isCancel(err)) {
setError(err);
}
}
.finally(() => {
if (!canceled) {
setLoading(false)
}
)
}
setLoading(true);
getData();
return () => {
canceled = true;
source.cancel();
}
}, [currentPage])
return { data, error, loading }
}
Upvotes: 2
Reputation: 11
function fetchData(currentPage) {
const [error, setError] = useState(null)
const [data, setData] = useState([])
const [loading, setLoading] = useState(true)
useEffect(async () => {
async function getData() {
axios.get(`https://${MY_API}${currentPage}`)
.then((res) => setData(res.data))
.catch((err) => setError(err))
.finally(() => setLoading(false))
}
await getData()
getData()
}, [currentPage])
return { data, error, loading }
}
Upvotes: 0