Reputation: 6953
What are the types of React.js's state and event?
In my code below, I can only make it work by using type: any
but it's just a hack. How can I use the right types for them?
In my custom hooks:
If I use function useFormFields(initialState: object)
, I get:
// 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.
If I use function(event: React.FormEvent)
(which is true), I have this error:
Property 'id' does not exist on type 'EventTarget'.ts(2339)
If I use function(event: object)
, I have this error:
Property 'target' does not exist on type 'object'.ts(2339)
That's odd because below I use const handleSubmitItem = (event: React.FormEvent)
and it works.
The answers I've found (like this one) don't work for me because 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>
);
}
Upvotes: 1
Views: 5547
Reputation: 522
I've made some corrections in the solution that you found. Hope it helps!
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>
);
}
Upvotes: 3
Reputation: 4272
Generals! the answer!
hope it helps!
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>
);
}
Upvotes: 1
Reputation: 5629
Since every component may be different you need to define the state and props types by yourself. There are some basic types defined for react (because every component may have children
for example) but as i said, you will need to define your own types.
An example for a functional component:
const App: React.FC<{ message: string }> = ({ message }) => (
<div>{message}</div>
);
The example above could also be written like so:
type MyType = { message: string }
const App: React.FC<MyType> = ({ message }) => (
<div>{message}</div>
);
further reading here:
https://github.com/typescript-cheatsheets/react-typescript-cheatsheet#section-2-getting-started
Upvotes: 1