Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use the useQuery hook to populate state in other hooks?

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.

like image 823
ElektrikSpark Avatar asked Apr 02 '19 10:04

ElektrikSpark


People also ask

Can you use a hook in another hook React?

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.

Can I use useQuery inside useEffect?

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).

How do I change state using useState hook?

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 use the same hook Share State?

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.


1 Answers

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>
}
like image 171
Shubham Khatri Avatar answered Oct 10 '22 05:10

Shubham Khatri