1

I have this custom hook to call the API

import { useState, useCallback } from 'react';

interface OptionsShape {
  method: 'GET' | 'POST';
}

interface InitStateShape {
  data: any;
  success: boolean;
  loading: boolean;
  error: Error | null;
}

const useAPI = (initialData = null) => {
  const initialState: InitStateShape = {
    data: initialData,
    success: false,
    loading: false,
    error: null,
  };

  const [response, setResponse] = useState(initialState);

  const callAPI = async (URL: string, options: OptionsShape) => {
    setResponse({ ...response, success: false, loading: true });

    try {
      const response = await fetch(URL, options);
      if (response.status < 200 || response.status >= 300)
        throw new Error('Failed to fetch');
      const json = await response.json();
      setResponse({
        data: json,
        success: true,
        loading: false,
        error: null,
      });
    } catch (e) {
      setResponse({
        data: initialData,
        success: false,
        loading: false,
        error: e.message,
      });
    }
  };

  return [response, useCallback(callAPI, [])];
};

export { useAPI };

I'm calling it with

import { useAPI } from '../hooks/useAPI';
...
const [response, callAPI] = useAPI();
...
callAPI('https://api.mysite.com/test', { method: 'GET' });

The error I get on callAPI is:

This expression is not callable.
  Not all constituents of type '{ data: null; success: boolean; loading: boolean; error: null; } | ((URL: string, options: OptionsShape) => Promise<void>)' are callable.
    Type '{ data: null; success: boolean; loading: boolean; error: null; }' has no call signatures.ts(2349)
1
  • 1
    This has to do with the difference between Tuples and Arrays in Typescript. If you specify the type of the return value, the error is gone. The "as const" (answer below) also works, but smells a bit like a workaround. Commented Mar 28, 2023 at 13:46

1 Answer 1

7

The return value is inferred as an array and not as a tuple. You can change that by adding as const:

 return [response, useCallback(callAPI, [])] as const;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.