reactjs - 如何使用 Typescript 将对象传递给子自定义 React 功能组件
问题描述
并感谢您花时间阅读本文。
我正在尝试使用带有 AirBnB 配置的 eslint 来学习 Typescript。像映射一组对象并为每个对象创建一个自定义功能组件这样简单的事情给了我下一个错误:
Argument of type '(product: ProductType) => JSX.Element' is not assignable to parameter of type '(value: object, index: number, array: object[]) => Element'.
这是父组件 ProductGrid:
const ProductGrid: React.FC = () => {
const products = [
{
id: "string1",
name: "string1",
price: {
formatted_with_symbol: "string1"
},
description: "string1",
},
...
];
return (
<div>
<Grid container spacing={3}>
<Grid item xs={12} md={6} lg={4}>
{products.map((product: ProductType) => (
<Product key={product.id} product={product} />
))}
</Grid>
</Grid>
</div>
);
};
export default ProductGrid;
这是子组件产品:
const Product: React.FC<ProductTypeAsProps> = ({product}: ProductTypeAsProps) => {
const [loading, setLoading] = useState(true);
setTimeout(() => {
setLoading(false);
}, 3000);
return (
<Box className="product">
<Card className="card">
<CardContent className="content">
{loading ? (
<div className="skeleton">
<Skeleton
variant="text"
animation="wave"
component="h2"
width="65%"
/>
</div>
) : (
<div>
<p>{product.name}</p>
<p>{product.description}</p>
<p>{product.price.formatted_with_symbol}</p>
</div>
)}
</CardContent>
</Card>
</Box>
);
};
export default Product;
和类型声明:
export type ProductType = {
id: string;
name: string;
price: {
formatted_with_symbol: string;
};
description: string;
assets: [
{
id: string;
filename: string;
url: string;
}
];
};
export interface ProductTypeAsProps {
product: ProductType;
}
我也有一个 .eslintrc :
{
"extends": ["airbnb-typescript", "react-app", "prettier"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
"project": "tsconfig.json"
},
"plugins": ["prettier", "@typescript-eslint", "react-hooks"],
"settings": {
"import/resolver": {
"typescript": {
"alwaysTryTypes": true
}
}
},
"rules": {
"@typescript-eslint/no-explicit-any": [
"error",
{
"ignoreRestArgs": true
}
],
}
}
和 tsconfig :
{
"compilerOptions": {
"target": "es5",
"lib": ["es6", "dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"noImplicitAny": false
},
"include": ["src"]
}
我已经创建了这个代码框,但当然,lint 错误并没有出现在那里,我在 VsCode 中对此进行了编码。
有什么帮助吗?因为这在 javascript 中是相当标准的。
解决方案
我可以通过查看错误消息来判断问题所在:
'(product: ProductType) => JSX.Element' 类型的参数不能分配给'(value: object, index: number, array: object[]) => Element' 类型的参数。
这表示您在内部使用的 map 函数products.map()
是 type (product: ProductType) => JSX.Element
。它说这不是您的products
数组的有效映射器,因为products.map()
需要一个 map 类型的函数(value: object, index: number, array: object[]) => Element
。
为什么会期待这个?
此错误意味着products
您的实际代码中的变量具有类型object[]
。(product: ProductType)
您正试图通过在您的内部使用来弥补那种模糊的类型,map()
但这不起作用。在此处键入参数意味着您的 map 函数只能处理类型的对象,ProductType
但它需要处理任何object
因为products
是一个object
.
相反,您需要做的是使您的products
变量具有 type ProductType[]
。我认为您是从实际代码中的 API 获取这些数据的?因此,请确保 API 调用返回ProductType[]
而不是object[]
.
作为快速修复,您可以在映射数组之前断言数组的类型,但最好从源头解决问题。
{(products as ProductType[]).map((product) => (
<Product key={product.id} product={product} />
))}
推荐阅读
- java - 如何用 db 的结果填充 jsp 页面上的表格?
- node.js - 如何使用 mongoose 和 node.js 在多个 mongodb 集合中插入数据
- c# - 如何在调用文件 URL 以通过 Internet Explorer 下载时包含登录凭据?
- r - WinBUGS中计算后验分布的代码语法
- html - 悬停选择器在搜索栏中移动 svg
- django - 无法在 django 中过滤或搜索不同语言的数据
- javascript - 为什么这个简单的 async - promise - reduce 代码有效?
- spring - MyBatis - 如何连接同一个表中的多个列
- amazon-web-services - 在 Lambda@Edge 中创建签名 Cookie 以进行受限分发
- angular - 角度 8 表格重置,值无法正常工作