I am new to React.js, but am attempting to put together a simple application using TypeScript /TSX. The application contains a form that requires validation. I had it working by assigning handlers to each input and updating state accordingly, but this is a bit cumbersome (even for the small form I am creating):
export interface AddInventoryRowProps {
catOptions : Array<any>,
conditionOptions: Array<any>
}
export interface AddInventoryState {
title: string,
sku: string,
mpn: string,
catID : string,
conditionID: string,
price: string,
isCategoryValid : boolean,
isMPNValid : boolean,
isSKUValid : boolean,
isTitleValid : boolean,
isPriceValid : boolean,
isConditionValid : boolean
}
export class AddInventoryRow extends React.Component<AddInventoryRowProps, AddInventoryState> {
constructor(props : AddInventoryRowProps) {
super(props);
this.state = { title: "",
sku: "",
mpn: "",
catID: "",
price: "",
conditionID: "",
isCategoryValid: false,
isMPNValid: false,
isPriceValid: false,
isSKUValid: false,
isTitleValid: false,
isConditionValid: false}
this.handleCatChange = this.handleCatChange.bind(this);
this.handleConditionChange = this.handleConditionChange.bind(this);
this.handlePriceChange = this.handlePriceChange.bind(this);
this.handleSKUChange = this.handleSKUChange.bind(this);
this.handleSubmitClick = this.handleSubmitClick.bind(this);
this.handleMPNChange = this.handleMPNChange.bind(this);
this.handleTitleChange = this.handleTitleChange.bind(this);
}
Every "handle" function would look something like this:
handleMPNChange(ev : ChangeEvent<HTMLInputElement>) {
this.setState( {isMPNValid: (ev.currentTarget as HTMLInputElement).value != "" });
this.setState( {mpn: (ev.currentTarget as HTMLInputElement).value });
}
with a corresponding input element in the render() function:
<div className="form-group">
<label>UPC/MPN</label>
<input name="mpn" onChange={this.handleMPNChange} value={this.state.mpn} id="mpn"
className={this.state.isMPNValid ? "form-control form-control-sm"
: "form-control form-control-sm error is-invalid" } />
</div>
I would like to make a single input handler, similar to the example from the React website. However, due the TypeScripts's "typing", the following does not work in my .txs file:
handleChange(ev : ChangeEvent<HTMLInputElement>) {
const target : HTMLInputElement = ev.currentTarget as HTMLInputElement;
const name : string = target.name;
const value: string = target.value;
this.setState( {[name]: value});
}
To elaborate, it gives the following error:
Argument of type '{ [x: string]: string; }' is not assignable to parameter of type 'AddInventoryState | ((prevState: Readonly<AddInventoryState>, props: AddInventoryRowProps) => Add...'.
Type '{ [x: string]: string; }' is not assignable to type 'Pick
Removing the [] from name gives a similar error. Now I understand I could probably resolve this by simply specifying a type of any instead of AddInventoryState when creating my class, but this does not seem like a proper fix.
It is probably something simple, but how does one approach this in TypeScript?
Thanks.