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');