reactjs - TypeScript React 中的对象可能为空
问题描述
使用此代码:
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;
};
解决方案
Typescript 将类型分配给 JavaScript 变量。大多数情况下,当您使用 TS 时,您应该在使用前定义变量类型。但是,如果可能,TS 有时可以推断变量的类型。
似乎您将 JS 代码复制粘贴到 TypeScript 中并试图使其工作。所以首先我建议为你要使用的变量定义类型,这样 TS 会设置正确的类型。
useState
对makestate.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
。您可能应该知道什么是返回数据的 JSON 类型结构,fetch
因此请正确输入。
从您的代码中我可以猜到,该数据类型可能看起来像这样
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;
};
推荐阅读
- c++ - 如何在两个 boost::intrusive::slist 对象之间传输节点
- php - 使用 Ajax 方法通过 Kartik FileInput Yii2 小部件成功上传后更新图像时图像为空
- android - 如何在不触发 onTabSelectedListener 的情况下设置 tablayout 位置?
- javascript - React Router V4 - 道具没有从父组件传递给 this.props.children
- javascript - 为 userData websocket 实现 ping/pong
- javascript - 传递给函数的参数在等待后消失
- agens-graph - 如何避免 AgensGraph 上的重复顶点节点?
- php - 如何在编辑页面显示记录?
- git - Git合并已修改相同文件的不同功能
- python - 网页抓取新手