Reputation: 1417
devs,
I have decided to finally learn react hooks with what I thought would be a simple project. I can't quite figure out how I re-fetch an API using react hooks. Here is the code I have so far.
import React, { useState, useEffect } from "react"
import useFetch from "./utils/getKanya"
const kanye = "https://api.kanye.rest"
const Index = () => {
let [kanyaQuote, setKanyeQuote] = useState(null)
let data = useFetch(kanye)
const getMore = () => {
setKanyeQuote(useFetch(kanye))
}
return (
<>
<h1>Welcome to Next.js!</h1>
<p>Here is a random Kanye West quote:</p>
{!data ? <div>Loading...</div> : <p>{!kanyaQuote ? data : kanyaQuote}</p>}
<button onClick={getMore}>Get new quote</button>
</>
)
}
export default Index
null
This is the error I get Error: Invalid hook call...
I would greatly appreciate any guidance you can provide on this.
Upvotes: -1
Views: 553
Reputation: 1639
The issue here is, that you can only use hooks directly inside the root of your component. It's the number 1 'rule of hooks'. You can read more about that here
const getMore = () => {
setKanyeQuote(useFetch(kanye) /* This cannot work! */)
}
There are a few ways you could work around that. Without knowing the internal logic in your useFetch
-hook I can only assume you are able to change it.
One way to work around that would be to change the logic of your custom useFetch
hook to provide some form of function that fetches the data and updates the state internally. It could then look something like this:
const { data, doFetch } = useFetch(kanye);
useEffect(() => {
doFetch(); // initialFetch
}, []);
const getMore = () => {
doFetch();
};
// ...
You would then need to change the internal logic of your useFetch
-hook to use useState
internally and expose the getter of it. It would look something like this:
export const useFetch = (url) => {
const [data, setData] = useState(null);
const doFetch = () => {
// Do your fetch-Logic
setData(result);
};
return { data, doFetch };
};
If you only want to manage the state of the loaded data in the parent component, you could just provide the wrapped fetch function through the hook; Something like that:
const doFetch = useFetch(kanye);
const [data, setData] = useState(null);
useEffect(() => {
setData(doFetch()); // initialFetch
}, []);
const getMore = () => {
setData(doFetch())
};
// ...
You would then need to change the internal logic of your useFetch
-hook to not have any internal state and just expose the wrapped fetch. It would look something like this:
export const useFetch = (url) => {
const doFetch = () => {
// Do your fetch-Logic
return result;
};
return doFetch;
};
Upvotes: 1