React Hooks TypeScript 事件和状态类型
Posted
技术标签:
【中文标题】React Hooks TypeScript 事件和状态类型【英文标题】:React Hooks TypeScript event and state types 【发布时间】:2020-05-25 00:31:48 【问题描述】:React.js 的状态和事件有哪些类型?
在下面的代码中,我只能通过使用type: any
使其工作,但这只是一个 hack。我怎样才能为他们使用正确的类型?
在我的自定义钩子中:
如果我使用function useFormFields(initialState: object)
,我会得到:
// value=inputs.item error:
Property 'item' does not exist on type 'object'.ts(2339)
// onChange function error:
(JSX attribute) onChange: object
No overload matches this call.
如果我使用function(event: React.FormEvent)
(这是真的),我有这个错误:
Property 'id' does not exist on type 'EventTarget'.ts(2339)
如果我使用function(event: object)
,我有这个错误:
Property 'target' does not exist on type 'object'.ts(2339)
这很奇怪,因为下面我使用 const handleSubmitItem = (event: React.FormEvent)
并且它有效。
我找到的答案(如this one)对我不起作用,因为Property 'id' does not exist on type 'EventTarget'
import React, useState from 'react';
import TextField from '@material-ui/core/TextField';
import IconButton from '@material-ui/core/IconButton';
import AddShoppingCartIcon from '@material-ui/icons/AddShoppingCart';
/**
* Custom hooks for input fields.
* @param initialState initialState for Input Fields
*/
function useFormFields(initialState: any)
const [inputs, setValues] = useState(initialState);
return [
inputs,
function(event: any)
setValues(
...inputs,
[event.target.id]: event.target.value
);
];
export default function FormPropsTextFields()
const [inputs, handleInputChange] = useFormFields(
item: '',
quantity: '',
store: ''
);
const handleSubmitItem = (event: React.FormEvent) =>
event.preventDefault();
console.log(inputs);
;
return (
<form
className=classes.root
noValidate autoComplete="off"
onSubmit=handleSubmitItem
>
<div>
<TextField
required id="item"
label="Item"
value=inputs.item
onChange=handleInputChange
/>
<TextField
id="quantity"
label="Quantity"
type="number"
value=inputs.quantity
onChange=handleInputChange
InputLabelProps=
shrink: true,
/>
<TextField
id="store"
label="Store"
type="search"
value=inputs.store
onChange=handleInputChange
/>
<IconButton
type="submit"
color="primary"
aria-label="add to shopping cart"
>
<AddShoppingCartIcon />
</IconButton>
</div>
</form>
);
【问题讨论】:
【参考方案1】:我对您找到的解决方案进行了一些更正。 希望对您有所帮助!
import React, useState from 'react';
import TextField from '@material-ui/core/TextField';
import IconButton from '@material-ui/core/IconButton';
import AddShoppingCartIcon from '@material-ui/icons/AddShoppingCart';
/**
* Custom hooks for input fields.
* @param initialState initialState for Input Fields
*/
export interface MyModel
item: string
quantity: string
store: string
function useFormFields<T>(initialState: T): [T, (event: React.ChangeEvent<htmlTextAreaElement | HTMLInputElement>) => void]
const [inputs, setValues] = useState<T>(initialState);
return [
inputs,
function (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>)
setValues(
...inputs,
[event.target.id]: event.target.value
);
];
export default function FormPropsTextFields()
const [inputs, handleInputChange] = useFormFields<MyModel>(
item: '',
quantity: '',
store: ''
);
const handleSubmitItem = (event: React.FormEvent) =>
event.preventDefault();
console.log(inputs);
;
return (
<form
className=classes.root
noValidate autoComplete="off"
onSubmit=handleSubmitItem
>
<div>
<TextField
required id="item"
label="Item"
value=inputs.item
onChange=handleInputChange
/>
<TextField
id="quantity"
label="Quantity"
type="number"
value=inputs.quantity
onChange=handleInputChange
InputLabelProps=
shrink: true,
/>
<TextField
id="store"
label="Store"
type="search"
value=inputs.store
onChange=handleInputChange
/>
<IconButton
type="submit"
color="primary"
aria-label="add to shopping cart"
>
<AddShoppingCartIcon />
</IconButton>
</div>
</form>
);
【讨论】:
谢谢@nightElf,让我试试然后回复你。【参考方案2】:由于每个组件可能不同,您需要自己定义 state 和 props 类型。为 react 定义了一些基本类型(例如,因为每个组件都可能有 children
),但正如我所说,您需要定义自己的类型。
功能组件的示例:
const App: React.FC< message: string > = ( message ) => (
<div>message</div>
);
上面的例子也可以这样写:
type MyType = message: string
const App: React.FC<MyType> = ( message ) => (
<div>message</div>
);
在此处进一步阅读:
https://github.com/typescript-cheatsheets/react-typescript-cheatsheet#section-2-getting-started
【讨论】:
谢谢@messerbill,让我试试,然后回复你。【参考方案3】:将军们!答案!
希望对你有帮助!
import IconButton from '@material-ui/core/IconButton';
import TextField from '@material-ui/core/TextField';
import AddShoppingCartIcon from '@material-ui/icons/AddShoppingCart';
import React, useState from 'react';
export interface MyModel
item: string;
quantity: string;
store: string;
/**
* Custom hooks for input fields.
* @param initialState initialState for Input Fields
**/
function useFormFields<T>(initialState: T)
const [inputs, setValues] = useState(initialState);
return [
inputs,
function(event: React.FormEvent)
const name, value = event.currentTarget;
setValues(
...inputs,
[name]: value
);
];
export default function FormPropsTextFields()
const [inputs, handleInputChange] = useFormFields<MyModel>(
item: '',
quantity: '',
store: '',
);
const handleSubmitItem = (event: React.MouseEvent<HTMLButtonElement>) =>
event.preventDefault();
/***
make sure to have whatever attribute you want in the "html tag"
*/
const name, value = event.currentTarget;
console.log(inputs);
;
return (
<form
className=classes.root
noValidate autoComplete="off"
>
<div>
<TextField
required id="item"
label="Item"
name="Item"
value=inputs.item
onChange=handleInputChange
/>
<TextField
id="quantity"
label="Quantity"
name="Quantity"
type="number"
value=inputs.quantity
onChange=handleInputChange
InputLabelProps=
shrink: true,
/>
<TextField
id="store"
label="Store"
name="Store"
type="search"
value=inputs.store
onChange=handleInputChange
/>
<IconButton
type="button"
color="primary"
aria-label="add to shopping cart"
onClick=handleSubmitItem
>
<AddShoppingCartIcon />
</IconButton>
</div>
</form>
);
【讨论】:
谢谢@Emesto,让我试试然后回复你。 抱歉,差距过大。你的答案返回这些错误:property 'name' does not exist on type 'EventTarget & Element'.
如果我保留[event.target.id]: event.target.value
,它会返回:Property 'id' does not exist on type 'EventTarget'.
以上是关于React Hooks TypeScript 事件和状态类型的主要内容,如果未能解决你的问题,请参考以下文章
如何在 React with Typescript 中使用和指定通用 Hooks?
基于 React hooks + Typescript + Cesium 的 三维 webgis 实战系列教程
React Typescript with hooks:最大更新深度超出错误
状态上不存在属性 - 使用带有 TypeScript 的 React Router Hooks