[英]Reactjs Typerscript: Property 'toLowerCase' does not exist on type 'never'
Im trying to filter data with multiple key value in reactjs with tsx. 我试图在带有tsx的reactjs中过滤具有多个键值的数据。 Cards.tsx is a parent component and ShipmentCard.tsx is a child. Cards.tsx是父组件,而ShipmentCard.tsx是子组件。 I'm getting Property 'toLowerCase' does not exist on type 'never'
error. 我收到Property 'toLowerCase' does not exist on type 'never'
错误的Property 'toLowerCase' does not exist on type 'never'
。 I just want to return the related object based on search criteria. 我只想根据搜索条件返回相关对象。 Can anyone let me know where I made a mistake? 谁能告诉我我在哪里犯错了?
Cards.tsx 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" } ] }
Component
is a generic interface with two type parameters: The type of your props, and the type of your state. Component
是具有两个类型参数的通用接口:道具的类型和状态的类型。 Your component doesn't seem to have props so you can just use object
or {}
for the props interface, but you do have state, so you need to say what shape that state has: 您的组件似乎没有道具,因此您只能将object
或{}
用于道具接口,但是您确实有状态,因此您需要说明该状态的形状 :
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: ""
};
// ...
}
Separately, the next couple of problems I suspect you'll have are: 另外,我怀疑您接下来会遇到的两个问题是:
You're not checking that fetch
succeeded. 您没有检查是否成功fetch
。 You're not alone in this, it's a very common error (so common I wrote it up on my anemic little blog). 您并不孤单,这是一个非常常见的错误(很常见,我在贫乏的小博客上写下了它 )。 You need to add a check to your fetch
call: 您需要在fetch
调用中添加一张支票:
fetch("http://localhost:3001/shipments") .then(response => { if (!response.ok) { throw new Error("HTTP error " + response.status); } return response.json(); }) // ...
You're not handling errors from fetch
. 您不处理来自fetch
错误。 loadShipmentList
should either return the promise chain (and then componentDidMount
and other places it's used would handle errors) or handle/report errors itself. loadShipmentList
应该返回承诺链(然后componentDidMount
及其使用的其他位置将处理错误)或自身处理/报告错误。
You're setting card
to the result of parsing your JSON. 您正在将card
设置为解析JSON的结果。 Your code assumes card
is an array, but the JSON's top level isn't an array, it's an object with a shipments
property (which is an array). 您的代码假设card
是一个数组,但是JSON的顶层不是数组,它是一个带有shipments
属性的对象(它是一个数组)。 I suspect you meant to set card
(which should be cards
, plural, or shipments
) to the shipments
property of the returned data: 我怀疑您是想将card
(应该是cards
,plural或shipments
)设置为返回数据的shipments
属性:
.then(({shipments}) => this.setState({ card: shipments })); // ^^ ^^ ^^^^^^^^^
There may be further issues, but the main answer above should address the never
issue, and hopefully these further hints have helped. 可能还有其他问题,但是上面的主要答案应该解决never
问题,希望这些进一步的提示有所帮助。
In a comment you've said that when you give card
a type, this code causes an error: 在评论中,您说过,当您给card
指定类型时,此代码会导致错误:
const filteredData = this.state.card.filter(item => {
return Object.keys(item).some(key =>
item[key].toLowerCase().includes(lowercasedFilter)
);
});
If you expect the shape of the data in the JSON to be variable, you could declare card
as any[]
(or perhaps Record<string,string>[]
) and then that dynamic code would work. 如果您希望JSON中的数据形状可变,则可以将card
声明为any[]
(或也许Record<string,string>[]
),然后该动态代码将起作用。 But only if you want the component driven by the JSON. 但仅当您希望组件由JSON驱动时。 Otherwise, update the code to use the typesafe property names: 否则,更新代码以使用typesafe属性名称:
const filteredData = this.state.card.filter(({id, name, total, status, userId}) =>
`${id}\t${name}\t${total}\t${status}\t${userId}`.toLowerCase().includes(lowercasedFilter)
);
The compiler doesn't real type of state.card[...], becouse it's declared as array. 编译器不是state.card [...]的真实类型,因为它被声明为数组。 The most simple way is to declare this as any[] 最简单的方法是将其声明为any []
state = {
card: [] as any[],
filter: ""
};
Or describe data type explicit 或显式描述数据类型
interface Card {
"id": string,
"name": string,
"total": string,
"status": string,
"userId": string
}
...
state = {
card: [] as Card[],
filter: ""
};
Or by object example 或通过对象示例
const cardSample = {
"id": "123",
"name": "Heromisha",
"total": "1000",
"status": "ACTIVE",
"userId": "E222"
};
type Card = typeof cardSample;
...
state = {
card: [] as Card[],
filter: ""
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.