Search code examples
reactjsnext.jsreact-hooksserver-side-renderingswr

Is it possible to call useSWR from outside a useEffect?


My code basically looks like this:

export default  function myComponent() {
    async function getResults(myParams ){


      const { data, error } = useSWR('/api/blah>myParams=' + myParams );    
  
      //do some other stuff...

      return data;
    }

  useEffect(() => {
      let myParams = someLogicToGetDynamicParams();

      myresults=  getResults(myParams );

  }, [abc]);
  

   //...
}

But I get this error:

Unhandled Runtime Error
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

I understand that I should put useSWR inside of useEffect, but suppose my logic is getting long, and I want to refactor it. Does this mean I'm not allowed to refactor useSWR out into its own function (like my example above)?


Solution

  • you can simply destruct data and error outside the function and use them inside it.

    export default  function myComponent() {
        const { data, error } = useSWR('/api/blah');
    
        async function getResults(){
          //do some other stuff using 'data' and 'error'...
          return data;
        }
    
      useEffect(() => {
          let myresults = getResults();
      }, [abc]);
       //...
    }
    
    

    and if you want to make

    const { data, error } = useSWR('/api/blah');
    

    happen inside a function, you have to name this latter starting with the prefix 'use' to consider it as a hook

    async function useGetResults(){
       const { data, error } = useSWR('/api/blah')
       //do some other stuff using 'data' and 'error'...
      return data;
    }
    

    this should compile without errors, but the first approach is the way to go.