React + Typescript: получение ошибки типа, когда значения динамически устанавливаются в обработчике изменений

Я пытаюсь создать форму динамически на основе массива объектов.

Целью здесь является динамическое создание учетных записей пользователей при нажатии кнопки «Добавить пользователя» и отправка всего объекта состояния пользователей в бэкэнд.

Получение этой ошибки 'Элемент неявно имеет тип' any ', потому что type' {name: string; возраст: строка; } 'не имеет подписи индекса'.

Я новичок в реакции! Помощь будет оценена.

Что я делаю неправильно?

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;

person VJR08    schedule 04.04.2019    source источник


Ответы (2)


Во-первых, неправильный интерфейс для пользователя. age приводится к числу, а вы устанавливаете age в пустую строку "".

Во-вторых, когда вы используете Array.prototype.map, вы не используете индекс [id]. Реализация функции map () выглядит немного странно. Из MDN

Метод 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;
person henrik123    schedule 04.04.2019

Тип event.target.value - строка и не обязательно 'name' | 'age', поэтому при вызове:

users[value][event.target.name] = event.target.value;

Машинопись не может быть уверена, что 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;
}
person Xyrue    schedule 04.04.2019
comment
Идеально! Большое спасибо - person VJR08; 05.04.2019