Reputation: 41
I am currently implementing useSWR in order to fetch data from my express and mongo-db backend. I am able to fetch the data successfully from the database no problem. The following is the code i used to achieve this:
```//SWR method for hydration
const fetcher = (...args) => fetch(...args).then(res => res.json())
const { data, error } = useSWR('http://localhost:3000/appi/daily', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>```
This is then accessed using:
data.currentInfo.username
where username is one of the fields in the collection.
The problem comes in when i try to add this information into a state hook, which then returns the error rendered more hooks than during the previous render.
Removing the line:
const[displayNumber] = useState(data.currentInfo.randomString)
and any line that uses the state variable displayNumber then fixes the error completely.
I have included the relevant code below:
const fetcher = (...args) => fetch(...args).then(res => res.json())
const { data, error } = useSWR('http://localhost:3000/appi/daily', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
const[displayNumber] = useState(data.currentInfo.randomString)
//handler function for changing state variable
function handleNumChange(event){
console.log(event.target.value);
setNumber(event.target.value);
}
return(
<div>
<div>
<Navbar className="navbar"/>
<h2>{data.currentInfo.username}</h2>
<h2>{displayNumber}</h2>
In short im pulling the data with swr, adding this information to a state variable and then displaying it with a h2.
Could anyone enlighten me what is possibly wrong with this approach?
I have searched online for the error which says that it could be caused by useEffect hooks but there isn't any in my code.
Upvotes: 4
Views: 9934
Reputation: 844
The error describes you have more hooks than previous render. If you read the react docs, all useState
hooks should always be called every render. You can't have a conditional useState
while your code has an extra useState
bellow following:
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
That means if there is no error
and there is data
only then the line const[displayNumber] = useState(data.currentInfo.randomString)
will be called.
EDIT: Move it to the top will normally resolve your issue.
const fetcher = (...args) => fetch(...args).then(res => res.json())
const { data, error } = useSWR('http://localhost:3000/appi/daily', fetcher)
//const[displayNumber] = useState(data.currentInfo.randomString) //Needs null checks ofcourse
//With null checks
const[displayNumber] = useState((data && data.currentInfo && data.currentInfo.randomString) || undefined)
//OR
//const[displayNumber] = useState(data?.currentInfo?.randomString)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
Upvotes: 9