I am developing a hook in which I can pass a function that makes a web request and it returns isLoading, data and error.
const [isLoading, data, error] = useApi(getMovie, idMovie, someAction);
basically I have a hook (useApi) that receives 3 parameters:
- a function that resolves a web request
- the parameters of this web request
- and finally the call to a callback.
I use it like this:
const idMovie = { _id: "3" };
// callback function
const someAction = (data: unknown) => {
// do something
return data;
};
const [isLoading, data, error] = useApi(getMovie, idMovie, someAction);
useApi.tsx
import { AxiosPromise, AxiosResponse } from 'axios';
import { useState, useEffect } from 'react';
const useApi = (
apiFunction: (params: unknown) => AxiosPromise,
params = {},
callback: (data: unknown) => void
): [boolean, unknown, null | string] => {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<null | string>(null);
useEffect(() => {
apiFunction(params)
.then(({ data }: AxiosResponse) => {
setData(data);
setIsLoading(false);
if (callback) {
callback(data);
}
})
.catch(() => {
setError('Something went wrong');
setIsLoading(false);
});
}, []); //apiFunction, params, callback]
return [isLoading, data, error];
};
export default useApi;
getMovie corresponds to a function that solves a web request
import axios from "axios";
type getMovieParams = { _id: string };
const BASE_URL = "https://jsonplaceholder.typicode.com/todos/";
const getMovie = (params: getMovieParams): Promise<unknown> => {
if (params) {
const { _id } = params;
if (_id) {
const url = `${BASE_URL}/${_id}`;
return axios.get(url);
}
}
throw new Error("Must provide a query");
};
export default getMovie;
the code that calls this hook would look like this:
import "./styles.css";
import useApi from "./useApi";
import getMovie from "./api";
interface Movie {
userId: number;
id: number;
title: string;
completed: boolean;
}
export default function App() {
const idMovie = { _id: "3" };
// callback function
const someAction = (data: unknown) => {
// do something
return data;
};
const [isLoading, data, error] = useApi(getMovie, idMovie, someAction);
const dataResponse = error ? [] : data; //type Movie
console.log(dataResponse);
if (isLoading) {
return <div>Loading...</div>;
}
return (
<div>
{error && <div>{error}</div>}
-- Get Data Movie 1--
<p>{dataResponse.title}</p>
</div>
);
}
I am getting an typing error on this line:
<p>{dataResponse.title}</p>
this is because:
const dataResponse = error ? [] : data;
data is of type unknown, this is because it could be any type of data, but I want to specify in this case that the data type is 'Movie', the idea is to reuse this hook in another component and be able to say the type of data that will be obtained when this hook returns data.
this is my live code:
https://codesandbox.io/s/vigilant-swartz-iozn4
The reason for the creation of this question is to ask for your kind help to solve the typescript problems that are marked with a red line. (file app.tsx)
How can fix it? thanks
