#reactjs #typescript #react-component
#reactjs #typescript #реагирующий компонент
Вопрос:
Я пытаюсь создать форму динамически на основе массива объектов.
Цель здесь — динамически создавать учетные записи пользователей по нажатию кнопки «Добавить пользователя» и отправлять весь объект состояния пользователей в серверную часть.
Получение этой ошибки ‘Элемент неявно имеет тип ‘any’, потому что тип ‘{ name: string; age: string; }’ не имеет индексной подписи‘.
Я новичок в react! Помощь была бы оценена.
Что я делаю не так?
import * as React from "react";
interface State{
users:User[]
}
interface Props{
}
interface User{
name:string,
age:number;
}
class App extends React.Component<Props,State> {
state = {
users: [{name:"", age:""}],
}
handleChange = (value:number,event : React.ChangeEvent<HTMLInputElement>) => {
let users = [...this.state.users];
console.log(event.target.value);
users[value][event.target.name] = event.target.value;
this.setState({ users }, () => console.log(this.state.users))
}
addUser = () => {
this.setState((prevState) => ({
users: [...prevState.users, {name:"", age:""}],
}));
}
handleSubmit = (e:any) => {
e.preventDefault();
console.log(this.state.users)
}
render() {
let { users} = this.state
return (
<form onSubmit={this.handleSubmit} >
<button onClick={this.addUser}>Add new cat</button>
{
users.map((val, id)=> {
return (
<div key={id}>
<input
type="text"
name="name"
value={users[id].name}
onChange = {(e) =>this.handleChange(id,e)}
/>
<input
type="text"
name="age"
value={users[id].age}
onChange = {(e) => this.handleChange(id,e)}
/>
</div>
)
})
}
<input type="submit" value="Submit" />
</form>
)
}
}
export default App;
Ответ №1:
Тип event.target.value
является строковым и не обязательно 'name' | 'age'
таким при вызове:
users[value][event.target.name] = event.target.value;
Typescript не может быть уверен, что users[value]
будет иметь этот индекс. Вот почему вы можете либо изменить пользовательский интерфейс:
interface User {
name:string,
age:number;
[key: string]: string | number
}
или вы можете проверить, соответствует ли ключ ожидаемому значению:
const keyName = event.target.name
if (keyName === 'name' || keyName === 'age') {
users[value][keyName] = event.target.value;
}
Комментарии:
1. Идеально! Большое спасибо
Ответ №2:
Во-первых, интерфейс для пользователя неправильный. возраст преобразуется в число, и вы устанавливаете возраст в пустую строку «».
Во-вторых, когда вы используете Array.prototype.map, вы не используете индекс [id]. Реализация вашей функции map () выглядит немного странно. Из MDN
Метод map() создает новый массив с результатами вызова предоставленной функции для каждого элемента в вызывающем массиве.
Вы можете прочитать больше о map здесь
import * as React from "react";
interface Props{
}
interface User {
name: string;
age: number | string;
}
interface State {
users: User[];
}
class App extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
users: [{ name: "", age: "" }]
};
}
handleChange = (value: number, event: React.ChangeEvent<HTMLInputElement>) => {
let users = [...this.state.users];
users[value][event.target.name] = event.target.value;
this.setState({ users }, () => console.log(this.state.users));
};
addUser = () => {
this.setState(prevState => ({
users: [...prevState.users, { name: "", age: "" }]
}));
};
handleSubmit = (e: any) => {
e.preventDefault();
console.log(this.state.users);
};
render() {
const { users } = this.state;
return (
<form onSubmit={this.handleSubmit}>
<button onClick={this.addUser}>Add new cat</button>
{users.map((user, id) => {
return (
<div key={id}>
<input
type="text"
name="name"
value={user.name}
onChange={e => this.handleChange(id, e)}
/>
<input
type="text"
name="age"
value={user.age}
onChange={e => this.handleChange(id, e)}
/>
</div>
);
})}
<input type="submit" value="Submit" />
</form>
);
}
}
export default App;