skip to Main Content

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

2

Answers


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

    Login or Signup to reply.
  2. useSwr is usually used if you are fetching frequently changed data. for example, you want to show the price of ethereum on your website, you should use useSwr.

    const fetcher = async (url) => {
      const res = await fetch(url);
      const json = await res.json();
      // ?? will return second if json is undefined
      return json ?? null;
    };
    
    export const useGetData = (params) => {
      // construct URL here
      const URL= "base_url"+`${/prams}`
      const { data, ...rest } = useSWR(URL, fetcher, { refreshInterval: 10000 });
      
      return { myData: { data, ...rest } };
    };
    

    then you can call the above function in your component

    export default  function myComponent({params}) {
        const {myData}=useGetData(params)
    }
    

    I passed params as prop, you could pass it from getServerSideProps or you could get them in useEffect and store them in useState.

    useSwr itself a hook. hook means it is hooked into the react lifecycle. useSwr knows when to rerender the component. from docs

    SWR deep compares data changes by default. If the data value isn’t
    changed, a re-render will not be triggered.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search