Home > front end >  Custom Hooks with Typescript
Custom Hooks with Typescript

Time:10-11

I have been learning about custom hooks and wanted to implement them on a block of code that is repeated throughout my app. The repeated block is a try-catch block to fetch data from an API.

the hook:

const useFetch = (url: string, method: string) => {
    const [data, setData] = useState(null);
    const [errorMsg, setErrorMsg] = useState('');

    useEffect(() => {
        (async () => {
            try {
                const response = await api({ url, method });
                setData(response.data);
            } catch (error) {
                error instanceof Error && setErrorMsg(error.message);
            }
        })();
    }, [url, method]);

    return { data, errorMsg };
};

export default useFetch;

This is the code from a component before implementing the hook:

const Productivity = () => {
    const [productivity, setProductivity] = useState<IUser[]>([]);
    const [errorMsg, setErrorMsg] = useState<string>('');

    useEffect(() => {
        (async () => {
            try {
                const response = await api({ url: '/api/productivity', method: 'GET' });
                response.users && setProductivity(response.users);
            } catch (error) {
                error instanceof Error && setErrorMsg(error.message);
            }
        })();
    }, []);

    return <div>{productivity.length > 0 ? <ProductivityTable productivity={productivity} /> : <AlertMessage errorMsg={errorMsg} />}</div>;
};

The updated version of the same component:

const Productivity = () => {
    const { data: productivity, errorMsg } = useFetch('/users', 'GET');
    

    return (
        <div>
            {errorMsg && <AlertMessage errorMsg={errorMsg} />}
            {productivity && <ProductivityTable productivity={productivity} />}
        </div>
    );
};

If I run the app, everything runs smoothly, but I'm noticing that {productivity} is of type "never." What does that mean? How can I set the type of productivity to be an array of IUser? Do I need to? I'm not sure what the best practice is here.

CodePudding user response:

Change your hook to a generic function, with a parameter for the type of the returned data:

function useFetch<T>(url: string, method: string) {
  const [data, setData] = useState<T | null>(null);
  // the rest stays the same
};

Usage:

const { data: productivity, errorMsg } = useFetch<IUser[]>('/users', 'GET');
  • Related