Как правильно отловить event в react/typescript?

77
28 февраля 2022, 21:20

Есть метод, который меняет имя у добавленного объекта

const onChangeName = (title: any, id: number) => {
    const car = cars[id]
    car.title = title
    const changedCar = [...cars]
    changedCar[id] = car
    setCars(changedCar)
}

сразу при input:

<input type="text" placeholder="change name"
    onChange={() => onChange(car.title, car.id)} value={car.title}/>

хочу отловить event, но TypeScript выдаёт ошибку (пишет, что не может поменять title у undefined). На обычном React без ts всё работает.

<CarList
    cars={cars}
    onRemove={removeHandler}
    /*onChange={onChangeName}*/
    onChangeName={event => onChangeName(event.target.value, id)}
/>

UPD: Всё-таки динамически удалось поменять title таким образом

const onChangeName = (event: React.ChangeEvent<HTMLInputElement>) => {
    cars.map(car => {
        car.title = event.target.value
        return (
            console.log(car.title)
        )
    })
}

Но при этом меняется только 1 элемент, и то только в консоли. То есть, если title был "test", а мы дописали "123" , то он измениться только на "test1".

Answer 1
onChange={onChangeName}

Тут скорее всего 1 аргумент, причём event. Сравниваем с

const onChangeName = (title: any, id: number) => {

Очевидно, сигнатура не сходится. event под any прокатит (хотя получится фигня), а второго аргумента просто нет и он явно не подходит.

И не по теме:

const car = cars[id]

Тут ошибка. Должно быть

const car = { ...cars[id] }

Впрочем, можно сразу объединить со следующей строчкой и сделать так:

const car = { ...cars[id], title }
Answer 2

Насколько я понимаю, вы игнорируете основу React - Virtual Dom, как следствие, не пользуетесь состояниями, а сами объекты изменяете в обход реакта без setState. Какой смысл во всем этом? Погадать на "косточках", какие у вас могут быть ошибки в коде, которого мы не видим?

<input type="text" placeholder="change name" onChange={() => onChange(car.title,car.id)} value={car.title}/>

In React, mutable state is typically kept in the state property of components, and only updated with setState()

Это, конечно, не супер критично, но что у вас дальше "под капотом"?

const onChangeName = (event: React.ChangeEvent<HTMLInputElement>) => {
        cars.map(car => {
            car.title = event.target.value
            return (
                console.log(car.title)
            )
        })
    }

Не ясно, как бедняга map должен работать, если

array.map(callback[, thisObject]);

map() method creates a new array with the results of calling a provided function on every element in this array.

Вы же возвращаете:

return ( console.log(car.title))

Вам нужно начать использовать state и менять атрибуты (хотя бы автомобиля) через setState, т.к. сейчас вообще не понятно, чем вам можно помочь.

Сюда смотреть по стейтам https://reactjs.org/docs/state-and-lifecycle.html

Сюда по формам в реакт https://reactjs.org/docs/forms.html

Answer 3

Задан ли у вас тип для cars? Какое точно сообщение даёт TS?

Чтобы TS не говорил, что не может поменять title у undefined, нужно, чтобы он знал, что у car тип, имеющий поле title (any тут не годится: any может быть undefined, на что он, вероятно, и ругается – если тип для cars не задан – а для car он не задан явно, это видно по коду).

Простейшее, что можно попробовать – написать

const car: { title: string, [key]: any } = cars[id]

но лучше, конечно, создать тип car и использовать его, где надо (в частности, cars должен быть типа car[] и тип переменной car TS тогда выведет сам, хотя можно написать явно const car: car = cars[id]).

READ ALSO
babel не компилирует

babel не компилирует

настройки packagejson

75
Вставка изображения в DIV

Вставка изображения в DIV

Отлавливаю событие вставки изображения на элементе :

96
Конвертация аудио файла при загрузке на сервер

Конвертация аудио файла при загрузке на сервер

Подскажите, есть ли плагины или библиотеки для конвертации аудио файла из mp3 в ogg в момент загрузки на сервер?

111
Удаление заданного элемента

Удаление заданного элемента

Может кто-нибудь сказать мне, где ошибка? Я ввожу массив элементов в одно поле, а в другое поле - элемент, который хочу удалить из массиваМой...

77