使用以下代码:
const Products = () => {
const classes = useStyles();
const { data } = useFetch('/categories');
return (
<div className={classes.root}>
<GridList cellHeight={180} className={classes.gridList}>
<GridListTile key="Subheader" cols={6} style={{ height: 'auto' }} />
{data &&
data.map((category: CategoryInterface) => {
return (
<GridListTile key={category.id}>
<GridListTileBar title={category.name} />
</GridListTile>
);
})}
</GridList>
</div>
);
};
在映射之前,我在数据上得到“对象可能为空”,我尝试使用&&运算符来摆脱它,并且还尝试定义一个变量const categories = data as CategoryInterface[]
,但这表明我必须转换为首先未知,我应该怎么做呢?
这是useFetch钩子
import { useEffect, useState } from 'react';
export const useFetch = (url: string) => {
const [state, setState] = useState({ data: null, loading: true });
useEffect(() => {
setState(state => ({ data: state.data, loading: true }));
fetch(url)
.then(res => res.json())
.then(json => setState({ data: json, loading: false }));
}, [url, setState]);
return state;
};
答案 0 :(得分:0)
您的useFetch
Hokk应该是这样的,
import { useEffect, useState } from 'react';
export const useFetch = (url: string) => {
const [state, setState] = useState({ data: {}, loading: true }); //Don't assign null to state variable
useEffect(() => {
setState(state => ({ data: state.data, loading: true })); //Remove this line, this is not needed
fetch(url)
.then(res => res.json())
.then(json => setState({ data: json, loading: false }));
}, [url, setState]); //Replace [url, setState] with [] as your second argument to make useEffect work for first time.
return state;
};
您的用法应该是
const { data } = useFetch('/categories');
{data.length>0 &&
data.map((category: CategoryInterface) => {
return (
<GridListTile key={category.id}>
<GridListTileBar title={category.name} />
</GridListTile>
);
})
}
答案 1 :(得分:0)
Typescript将类型分配给JavaScript变量。通常,在使用TS时,应在使用前定义变量类型。但是,TS有时可能会推断出变量的类型。
似乎您将JS代码复制粘贴到TypeScript中并试图使其正常工作。因此,我首先建议为要使用的变量定义类型,以便TS可以设置正确的类型。
对useState
的初始调用使state.data
的类型为null
(这是唯一的TS知道的类型)。与JS不同,TS不允许在执行期间更改类型。因此,state.data
在程序执行期间将具有null
类型。
const [state, setState] = useState({ data: null, loading: true });
// Type of state is
// { data: null, loading: boolean }
要纠正此问题,您应该提前提供state
变量的类型。其中一个可能的值为null
。另一个可能的值-是从fetch
接收的数据。您可能应该知道fetch
返回的数据的JSON类型是什么,因此请按类型输入。
从我的代码中我可以猜到,该数据类型可能看起来像这样
type IData = CategoryInterface[];
CategoryInterface
看起来像
interface CategoryInterface {
id: string;
name: string;
}
因此IData
将是state.data
的第二种可能类型。因此,在state
通话期间分配useState
的类型
const [state, setState] = useState<{data: IData | null, loading: boolean}>({ data: null, loading: true });
但是您应该保留{data && data.map (/*...*/)}
的位置,因为state.data
在数据完全加载之前是不确定的。
完整代码
interface CategoryInterface {
id: string;
name: string;
}
type IData = CategoryInterface[];
export const useFetch = (url: string) => {
const [state, setState] = useState<{ data: IData | null, loading: boolean }>({ data: null, loading: true });
useEffect(() => {
setState(state => ({ data: state.data, loading: true }));
fetch(url)
.then(res => res.json())
.then(json => setState({ data: json, loading: false }));
}, [url, setState]);
return state;
};