Reputation: 12197
I have som react state that was defined as an interface and has specificall named keys...
I tried a solution below that should technically work based on the state keys, but it still gives me the error
{ [x: string]: string; }' provides no match for the signature ...
What is the best way to do this...
interface State {
responses: string,
comments: string,
}
state = {
responses: '',
comments: '',
};
handleChange = (e: React.ChangeEvent<HTMLInputElement>, value: string): void => {
const key = e.currentTarget.name;
Object.keys(this.state).forEach(k => {
if (k === key) this.setState({ [e.currentTarget.name]: value });
})
}
Upvotes: 8
Views: 13564
Reputation: 2221
If you declare state with type number then use this code for update state:
this.setState({ ...this.state, [event.currentTarget.name]: Number(event.target.value) });
If you declare state with type string then use this code for update state:
this.setState({ ...this.state, [event.currentTarget.name]: event.target.value });
Full code:
onChange =(event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ ...this.state, [event.currentTarget.name]: Number(event.target.value) });
}
Upvotes: 1
Reputation: 31
public onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({
[e.currentTarget.name]: e.currentTarget.value
} as { [K in keyof IState]: IState[K] });
};
IState
- interface of this.state
Upvotes: 3
Reputation: 15136
The return type of Object.keys()
is the generic string[]
rather than an array of the union of the keys of the object, so it's probably tricky to infer the correct types here. Moreover, in my experience, smart solutions have a tendency to break when newer versions of TypeScript or package type definitions are released, so in this case I would just help TypeScript with a signature on to the argument of setState
:
handleChange = (e: React.ChangeEvent<HTMLInputElement>, value: string): void => {
const key = e.currentTarget.name;
if (Object.keys(this.state).includes(key)) {
this.setState({[key]: value } as Pick<State, keyof State>);
}
}
Upvotes: 15
Reputation: 8413
One option would be instead of iterating through keys, to use switch statement. Although it will produce more code:
switch (key) {
case 'responses':
this.setState({ responses: value });
break;
case 'comments':
this.setState({ comments: value });
break;
}
Upvotes: 2