Reactjs Typescript:类型“never”上不存在属性“toLowerCase”
我正在尝试使用 tsx 在 reactjs 中过滤具有多个键值的数据。
Cards.tsx
是父组件,
ShipmentCard.tsx
是子组件。我收到
Property 'toLowerCase' does not exist on type 'never'
错误。我只想根据搜索条件返回相关对象。有人可以告诉我我在哪里犯了错误吗?
Cards.tsx
class Cards extends Component {
state = {
card: [],
filter: ""
};
componentDidMount() {
this.loadShipmentList();
}
handleChange = (event: any) => {
this.setState({ filter: event.target.value });
};
loadShipmentList() {
fetch("http://localhost:3001/shipments")
.then(response => response.json())
.then(data => this.setState({ card: data }));
}
render() {
const { card, filter } = this.state;
const lowercasedFilter = filter.toLowerCase();
const filteredData = this.state.card.filter(item => {
return Object.keys(item).some(key =>
item[key].toLowerCase().includes(lowercasedFilter)
);
});
return (
<Card className="Search-Bar">
<CardContent>
<Grid container spacing={3}>
<TextField
label="Search"
onChange={this.handleChange}
/>
</Grid>
</CardContent>
</Card>
<Grid container spacing={3}>
{filteredData.map((card: any) => (
<Grid item xs={12}>
<ShipmentCard key={card.id} value={card} />
</Grid>
))}
</Grid>
);
}
}
export default Cards;
{
"shipments": [
{
"id": "123",
"name": "Heromisha",
"total": "1000",
"status": "ACTIVE",
"userId": "E222"
},
{
"id": "456",
"name": "Honda",
"total": "3000",
"status": "ACTIVE",
"userId": "E111"
}
]
}
编译器无法识别 state.card[...] 的真实类型,因为它被声明为数组。 最简单的方法是将其声明为 any[]
state = {
card: [] as any[],
filter: ""
};
或者明确描述数据类型
interface Card {
"id": string,
"name": string,
"total": string,
"status": string,
"userId": string
}
...
state = {
card: [] as Card[],
filter: ""
};
或者通过对象示例
const cardSample = {
"id": "123",
"name": "Heromisha",
"total": "1000",
"status": "ACTIVE",
"userId": "E222"
};
type Card = typeof cardSample;
...
state = {
card: [] as Card[],
filter: ""
};
Component
是一个通用接口,具有两个类型参数:props 的类型和 state 的类型。您的组件似乎没有 props,因此您可以只使用
object
或
{
作为 props 接口,但您有 state,因此您需要说明该 state 具有什么
shape
:
interface Card {
id: string;
name: string;
total: string;
status: string;
userId: string;
}
interface CardsState {
card: Card[];
filter: string;
}
class Cards extends Component<object,CardsState> {
state: CardsState = {
card: [],
filter: ""
};
// ...
}
另外,我怀疑您会遇到的下几个问题是:
-
您没有检查
fetch
是否成功。您并不是唯一遇到这种情况的人,这是一个 非常 常见的错误(如此常见,我 在我的贫血小博客上写下了 它)。您需要在fetch
调用中添加检查:fetch("http://localhost:3001/shipments") .then(response => { if (!response.ok) { throw new Error("HTTP error " + response.status); } return response.json(); }) // ...
-
您没有处理来自
fetch
的错误。loadShipmentList
应该返回承诺链(然后componentDidMount
和使用它的其他地方会处理错误)或自己处理/报告错误。 -
您正在将
card
设置为解析 JSON 的结果。您的代码假设card
是一个数组,但 JSON 的顶层不是数组,它是一个具有shipments
属性的对象(它是一个数组)。我怀疑您的意思是将card
(应该是cards
,复数,或shipments
)设置为返回数据的shipments
属性:.then(({shipments}) => this.setState({ car​​d: shippings })); // ^^ ^^ ^^^^^^^^^
可能还有其他问题,但上述主要答案应该解决了
never
问题,希望这些进一步的提示有所帮助。
在一条评论中,您说当您为
card
指定类型时,此代码会导致错误:
const filteredData = this.state.card.filter(item => {
return Object.keys(item).some(key =>
item[key].toLowerCase().includes(lowercasedFilter)
);
});
如果您希望 JSON 中的数据形状可变,则可以将
card
声明为
any[]
(或者可能是
Record<string,string>[]
),然后该动态代码就可以正常工作。但前提是您希望组件由 JSON 驱动。否则,请更新代码以使用类型安全的属性名称:
const filteredData = this.state.card.filter(({id, name, total, status, userId}) =>
`${id}\t${name}\t${total}\t${status}\t${userId}`.toLowerCase().includes(lowercasedFilter)
);