«Элемент JavaScript не определен» в Array.prototype.find()

Я создаю приложение на ReactJS, которое использует теги для организации фотографий. Моя структура данных состоит из трех частей: (1) фотографии, (2) теги и (3) «теги изображений», которые представляют собой отношения между фотографией и тегом. Для фотографий с идентификаторами 9, 12 и 35 и тегами 4, 5 и 6 соответственно объект imageTag будет выглядеть следующим образом:

const imageTags = [
  {id: 1, imageId: 9, tagId: 4},
  {id: 2, imageId: 12, tagId: 5},
  {id: 3, imageId: 35, tagId: 6}
]

Компоненту «Тег» передается только идентификатор imageTag, по которому он сможет определить изображение, которому он назначен, и тег, который должен быть на этом изображении, например:

// props: imagetagId = {7}
const imageId = imageTags.find(element => element.id === props.imageTagId)

Это отлично работает для первоначального рендеринга. Однако когда пользователь пытается удалить метку с фотографии*, состояние приложения меняется, и я внезапно получаю сообщение об ошибке:

Uncaught TypeError: element is undefined

Чего я не понимаю, так это того, как «элемент» может быть неопределенным? Насколько я понимаю, он проходит через объект imageTags и проверяет каждый «элемент», поэтому я так назвал переменную. Я знаю, что это НЕ проблема «imageTags.find(...) не определена», дело не в том, что метод find не возвращает результатов. Для меня ошибка выглядит так, как будто сам элемент не определен... но как это возможно?

Вот функция, которая изменяет imageTags, когда пользователь пытается удалить тег:

// remove a specific imageTag from imageTags
const handleRemoveTag = (imageTagId) => {
  for (const [key, value] of Object.entries(imageTags)) {
    if (value.id == imageTagId) {
      delete imageTags[key];
    };
  };
};

*еще одна важная деталь, которую я обнаружил: эта ошибка НЕ ​​возникает при удалении ПОСЛЕДНЕГО тега в списке. Теги можно безопасно удалять по одному, начиная с последнего и заканчивая первым, но удаление тега из середины или начала приводит к этой ошибке. Я не уверен, почему это так, но это кажется актуальным для устранения неполадок.

Это объявление imageTags не является действительным JavaScript.

Robby Cornelissen 10.04.2024 04:22

В частности, это на самом деле массив или то, что здесь показано?

Dave Newton 10.04.2024 04:31

Я немного упрощаю, чтобы облегчить понимание вопроса. Объект ImageTags вложен в объект, содержащий другие данные приложения, но при вызове соответствующих функций им передается только эта часть. @RobbyCornelissen, что делает JavaScript недействительным? Возможно, я просто опечатал это в этом объяснении, я могу уточнить, если это не имеет смысла.

cdyswnnr 11.04.2024 05:32

Это недопустимое объявление объекта, поскольку в нем отсутствуют ключи. Это недопустимое объявление массива, поскольку в нем используются фигурные скобки. Поэтому люди не знают, что вы собираетесь использовать.

Robby Cornelissen 11.04.2024 06:59

@RobbyCornelissen ах, понятно, да, это имеет смысл. Я дважды проверил код, и это массив объектов в коде. Я отредактировал свой вопрос, чтобы отразить это. Однако функция handleRemoveTag возвращает объект с ключом 0, например: imageTags = {0: {id: 1 ...}, {id: 2}} Может ли это несоответствие быть причиной ошибки, с которой я столкнулся?

cdyswnnr 12.04.2024 00:17

На самом деле, если вы просто удалите ключ из массива (не меняя длину или тому подобное), вы легко столкнетесь с аналогичной ошибкой. Например: let a = [1,2]; delete a[a.length-1]; a.find(element=>element.key). Здесь a.length по-прежнему 2, но a[1] дает неопределенное значение.

qrsngky 12.04.2024 03:43
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
6
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Почему imageTags не может быть Array?

const imageTags = [               // <—-
  {id: 1, imageId: 9, tagId: 4},  //    |
  {id: 2, imageId: 12, tagId: 5}, //    |—- Array of Objects.
  {id: 3, imageId: 35, tagId: 6}  //    |
]                                 // <—-

Чтобы удалить конкретный imageTag из imageTags, если это Array, используйте эту процедуру.

const handleRemoveTag = (imageTagId) => {
  let index = imageTags.findIndex(element => element.id === imageTagId)
  imageTags.splice(index, 1)
}

Я только что попробовал это быстро и получаю ту же ошибку. Я попробую еще раз завтра, когда у меня будет больше времени, чтобы выявить потенциальные ловушки, которые я мог упустить. Когда я console.info(ImageTags), он говорит «Массив», поэтому его можно настроить так, как он у вас есть, но когда я console.info(typeof ImageTags), он говорит «объект», так что я не уверен. Скоро я смогу рассмотреть его более подробно и вернуться к вам.

cdyswnnr 11.04.2024 05:41

Array — это Object. Вместо этого проверьте Array.isArray.

Chukwujiobi Canon 11.04.2024 07:10

Могу подтвердить, это массив, а не словарь. Я обновил свой вопрос, чтобы отразить, как на самом деле настроен код. Однако я заметил, что результат, возвращаемый функцией handleRemoveTag, представляет собой словарь, например: {0: {id:1 ...}, {id: 2...}} Может ли это быть причиной этой ошибки? Это вызвано тем, что я пытаюсь использовать Object.entries, и исправляет ли это ваше решение? (Попробую это сейчас, чтобы посмотреть, смогу ли я сам ответить на эти вопросы с помощью кода)

cdyswnnr 12.04.2024 00:20

Поскольку вы сделали imageTagsArray, как я советовал, почему вы все еще используете Object.entries? Почему бы не использовать интерфейс Array? Я поделился возможной реализацией в своем ответе, не так ли? Используй это.

Chukwujiobi Canon 12.04.2024 07:11

Я вставил вашу реализацию. (Извините за задержку, это личный проект, и у меня есть на него совсем немного времени.) Я наблюдаю то же поведение, что описано в исходном вопросе, я могу удалять теги, начиная с последнего, назначенного изображению. и безопасно вернуться назад, но если я попытаюсь удалить первый тег, назначенный изображению, перед удалением последнего, все произойдет сбой.

cdyswnnr 17.04.2024 01:30

Поиграв еще немного с этим, я получил кое-что для работы, основываясь на вашем ответе! Спасибо за вашу помощь в этом!

cdyswnnr 17.04.2024 02:05

Другие вопросы по теме