I have a type product
within a React component:
type TProduct = {
name: string,
price: string,
stock: string
}
in which my component I wish to change the values through a input box:
const AddProductCard: React.SFC = () => {
const classes = useStyles();
const [product, setProduct] = React.useState({ product:{} as TProduct})
return (
<input
onChange={e => setProduct({...product ,product: {name: e.target.value }})}
/>
<input
onChange={e => setProduct({...product ,product: {stock: e.target.value }})}
/>
<input
onChange={e => setProduct({...product ,product: {price: e.target.value }})}
/>
)
}
I thought by adding ...product
it would copy over all the same values within product
and just change the value I wanted to but that didn't seem to work. It would set a new product object although it would just rewrite the whole content of the object with the only the most recent entered input.
I then attempted a different approach with an interface where:
interface IProduct {
name: string;
price: string;
stock: string;
}
and
const [product, setProduct] = React.useState<IProduct | undefined>(undefined);
and using a similar state change as I have shown previously, but alas that only occurred in another new bug (I guess I'm not sure how to properly use an interface in react).
Apart from supplying the methods for the onChange
events on the inputs, you will need to specify the value
as well. For instance,
value={product.name}
In addition, I am not sure why is the product
state deeply nested, as there is no need to go one level deeper in this scenario, This will reduce the complexity when you need to update the product state on each of the onChange
events. You only need to spread the current product state, followed by updating the property with the new values. For instance,
setProduct({
...product,
name: e.target.value
});
In addition, when it comes to typing the product state, there is no need to assert is as TProduct
. Given that the properties may be undefined, you can keep the following interface,
interface TProduct {
name: string;
price: string;
stock: string;
}
And set the typings for product
as Partial<TProduct>
.
Last but not least, if you are working with the newer versions of React, it will be sufficient to type your component as React.FC
.
This is how your component should look like.
const AddProductCard: React.FC = () => {
const classes = useStyles();
const [product, setProduct] = React.useState<Partial<TProduct>>({});
return (
<input
value={product.name || ''}
onChange={e => setProduct({...product, name: e.target.value })}
/>
<input
value={product.stock || ''}
onChange={e => setProduct({...product, stock: e.target.value })}
/>
<input
value={product.price || ''}
onChange={e => setProduct({...product, price: e.target.value })}
/>
)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With