Какой тип указать для обработчиков событий, привязанных к нескольким полям?

#reactjs #typescript

Вопрос:

У меня есть форма реакции с динамическими полями, основанная на этом уроке. Его необходимо изменить, чтобы он был совместим с машинописным текстом. Я получаю эту ошибку:

«Элемент неявно имеет тип»any», потому что выражение типа » any «не может использоваться для индексирования типа» {makeModel: строка; год: строка;}».»

  const handleCarChange = (e: any, index: number) => {
    const { name, value } = e.target;
    const list = [...carList];
    list[index][name] = value;  // TODO fix this typescript error
    setCarList(list);
  };
 

Комментарии:

1. общий carList массив

2. для события вы можете SyntheticEvent ввести React

Ответ №1:

Для использования типов с обработчиками щелчков вы можете попробовать использовать MouseEvent из React . Не уверен, что это решит проблему с ошибкой машинописи. Это выглядит по-другому.

 import { MouseEvent } from 'react';

const handleCarChange = (e: MouseEvent, index: number) => {
   const { name, value } = e.target;
   const list = [...carList];
   list[index][name] = value;  // TODO fix this typescript error
   setCarList(list);
};
 

Дальнейшее чтение.
https://fettblog.eu/typescript-react/events/

Ответ №2:

Этот урок плохой. И это только мое мнение.

Почему?

Во-первых, эта строка const list = [...carList]; не имеет никакого смысла.

Здесь автор учебника все еще изменяет массив

 list[index][name] = value;
 

Рассмотрим следующий пример:

 const list = [{ name: 1 }]
const newList = [...list]
newList[0]["name"] = 2

list // [{name: 2}]
 

Вы никогда не должны изменять состояние. Эта строка [...list] создает только поверхностную копию. Это просто новая ссылка на весь массив, но каждый элемент в массиве по-прежнему имеет ту же ссылку.

Давайте вернемся к вашей проблеме.

 
type Fn = (args: any) => any

type ChangeHandler = ChangeEventHandler<HTMLInputElement>

type WithIndex<T extends Fn> = (e: Parameters<T>[0], index: number) => void

const Component = () => {
  const [inputList, setInputList] = useState<State>([{ firstName: "", lastName: "" }]);

  const handleCarChange: WithIndex<ChangeHandler> = (e, index) => {
    const { name, value } = e.target;

    const newList = inputList.map((elem: Entity, i: number) =>
      i === index ? {
        ...elem,
        [name]: value
      } : elem)

    setInputList(newList);
  };

  return (
    <input
      onChange={e => handleCarChange(e, 0)}
    />
  )
}
 

Пожалуйста, имейте в виду, что для любого обработчика мыши вы всегда можете использовать встроенные типы, такие как ChangeEventHandler

Игровая площадка

Если вы хотите обновить свое состояние, пожалуйста, обратитесь к официальным шаблонам редактирования