使用typescript的泛型设置类型为useFetch



我有一个useFetch,我想给他发送一个字符串类型的参数URL,忘了提到它是消费API。我的问题是,它不承认结果。我在useFetch使用泛型类型。如果我使用在我的接口中创建的类型,一切都是干净的,没有错误。

但是我的想法是useFetch应该是不可知的。我从过滤器得到的错误是属性结果不存在类型>

useFetch代码。

import { useEffect, useState } from "react"
type useFetchState<T> = {
data: null | T;
}
export const useFetch = <T>( url: string )  => {
const [data, setData] = useState<useFetchState<T | null>>(null)
const [loading, setLoading] = useState<boolean>(false)
const [error, setError] = useState<string | null>(null)
const getData = (url:string) => {
setLoading(true)
return fetch(url)
.then((res) => {
const showError = {
err:true,
statuscode:res.status,
message:"Error in your request"
}
if(!res.ok){
throw showError;
}
return res.json()
})
.then((data) => {
setData(data)
})
.catch((err) => setError(err))
.finally(() => {
setLoading(false);
})
}
useEffect(() => {
getData(url)
}, [url])

return {data, loading, error}
}

主组件代码。

import { movieApi, movieApiResult } from "../../hooks/useFetch/interface";
import { useFetch } from "../../hooks/useFetch/useFetch";
import "./home.css";
const Home = () => {
const IMGPATH = "https://image.tmdb.org/t/p/w1280";
const { data } = useFetch<movieApi>(
"https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=04c35731a5ee918f014970082a0088b1&page=2"
);
return (
<div className="container">
{data?.results.map((item: movieApiResult) => (
<div
key={item.id}
className="item"
//onClick={() => handleClick(item.id)}
>
<img
src={`${IMGPATH}${item.poster_path}`}
alt={item.title}
className="image"
/>
<p>{item.title}</p>
<span>{item.vote_average}</span>
</div>
))}
</div>
);
};
export default Home;

接口
export interface movieApi {
page: number;
results: movieApiResult[];
total_pages: number;
total_results: number;
}
export interface movieApiResult {
adult: boolean;
backdrop_path: string;
genre_ids: number[];
id: number;
original_language: string;
original_title: string;
overview: string;
popularity: number;
poster_path: string;
release_date: string;
title: string;
video: boolean;
vote_average: number;
vote_count: number;
}

好,删除useFetchState工作,问题解决了,但如果我创建一个useContext,并将该数据发送到Home组件,错误再次出现在"结果"中。

type props = {
children: JSX.Element | JSX.Element[];
};
interface MoviesTypes {
data: movieApi | movieObject | null;
loading: boolean;
setUrl: Dispatch<SetStateAction<string>>;
handleClick: (id: number) => void;
IMGPATH: string;
}
const MoviesContext = createContext<MoviesTypes>({} as MoviesTypes);
export const MoviesProvider = ({ children }: props) => {
const [url, setUrl] = useState<string>(
"https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=04c35731a5ee918f014970082a0088b1&page=2"
);
const [ids, setIds] = useState<null | number>(null);
const { data, loading } = useFetch<movieApi | movieObject>(url);
const IMGPATH = "https://image.tmdb.org/t/p/w1280";
const handleClick = (id: number) => {
setUrl(
`https://api.themoviedb.org/3/movie/${id}?api_key=04c35731a5ee918f014970082a0088b1`
);
setIds(id);
};
return (
<MoviesContext.Provider
value={{
data,
loading,
setUrl,
handleClick,
IMGPATH,
}}
>
{children}
</MoviesContext.Provider>
);
};
export const useMovies = () => {
const context = useContext(MoviesContext);
return context;
};

我想这一定是一个相当简单的问题。但是我才刚刚开始打字呢。

您对useFetchState的使用略有偏差-它的类型是

{
data: null | T;
}

,然后你传递一个必须匹配它的值(通过useState)到它不是一个可能为空的对象data,而是null本身。

useState<useFetchState<T | null>>(null)

useFetchState对你也没什么用。我会将useState类型更改为null或T,不需要其他任何内容。

const [data, setData] = useState<T | null>(null)

在这种情况下,您不需要这样做:

type useFetchState<T> = {
data: null | T;
}

就像下面这样改变你的useFetch(如果你是。tsx格式,不要忘记<T,>):

export const useFetch = <T,>(url: string) => {
const [data, setData] = useState<T>();
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
...
}

一切都会好起来的。

我想在这里改变这个限制(因为你说它应该是不可知论的)from:

const [data, setData] = useState<useFetchState<T | null>>(null);

:

const [data, setData] = useState<any | null>(null); // even only any will do the job

因为你可能会响应作为对象的数组,甚至作为对象包含数据状态,等等……因此,您永远不会知道响应数据的确切类型。

相关内容

  • 没有找到相关文章

最新更新