I have been dealing with a few hook-related issues recently as I have been implementing hooks into a project of mine. I keep getting the error "Rendered more hooks than during the previous render."
It seems that the only way I can get my code to work is by putting the useQuery hook after all of the other hooks. This is a problem however as I want to populate some values of state with values from data on the query.
// code that doesn't error, but am not able to initialize state with query values
const [url, setUrl] = useState('')
const updateLink = useMutation(LINK_UPDATE_MUTATION, {
variables: {
id: props.id,
url
}
})
const { data, loading, error } = useQuery(LINK_QUERY, {
variables: {
id: props.id
}
})
if (loading) {
return <div>Loading...</div>
}
if (error) {
return <div>Error! {error.message}</div>
}
vs
// code that errors with 'Rendered more hooks than during the previous render.'
const { data, loading, error } = useQuery(LINK_QUERY, {
variables: {
id: props.id
}
})
if (loading) {
return <div>Loading...</div>
}
if (error) {
return <div>Error! {error.message}</div>
}
const updateLink = useMutation(LINK_UPDATE_MUTATION, {
variables: {
id: props.id,
url
}
})
const [url, setUrl] = useState(data.link.url)
I would expect that the useQuery hook could be used in a way to initialize other values with its query data.
If this isn't enough code or more explanation is needed just let me know. Thanks.
You can't use a hook inside another hook because it breaks the rule Call Hooks from React function components and the function you pass to useEffect is a regular javascript function. What you can do is call a hook inside another custom hook.
useQuery is a hook and as such cannot be used under a branch. This means that you must call useQuery inside your component and not under a branch statement (if/else/switch/useEffect).
To update the state, call the state updater function with the new state setState(newState) . Alternatively, if you need to update the state based on the previous state, supply a callback function setState(prevState => newState) .
Do two components using the same Hook share state? No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.
What you need to do is to update the state when the first hook results in a response. To do that you can make use of useEffect
hook. You need to render all hooks at the top of your functional component.
const [url, setUrl] = useState('')
const updateLink = useMutation(LINK_UPDATE_MUTATION, {
variables: {
id: props.id,
url
}
})
const { data, loading, error } = useQuery(LINK_QUERY, {
variables: {
id: props.id
}
})
useEffect(() => {
if(data && data.link) {
setUrl(data.link.url);
}
}, [data])
if (loading) {
return <div>Loading...</div>
}
if (error) {
return <div>Error! {error.message}</div>
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With