Ошибка undefined is not an object evaluating

Время на прочтение
11 мин

Количество просмотров 29K

В компании Rollbar, которая занимается созданием инструментов для работы с ошибками в программах, решили проанализировать базу из более чем 1000 проектов на JavaScript и найти в них ошибки, которые встречаются чаще всего. В результате они сформировали список из 10 наиболее часто встречающихся ошибок, проанализировали причины их появления и рассказали о том, как их исправлять и избегать. Они полагают, что знакомство с этими ошибками поможет JS-разработчикам писать более качественный код.

image

Сегодня мы публикуем перевод их исследования.

Методика анализа

В наши дни данные — это всё, поэтому мы нашли, проанализировали и проранжировали ошибки, которые чаще всего встречаются в JavaScript-проектах. А именно, были собраны сведения об ошибках по каждому проекту, после чего было подсчитано количество ошибок каждого вида. Ошибки группировались по их контрольной сумме, методику вычисления которой можно найти здесь. При таком подходе, если, например, в одном проекте обнаружена некая ошибка, которая после этого найдена где-то ещё, такие ошибки группируют. Это позволяет, после анализа всех участвующих в исследовании проектов, получить краткую сводку по ошибкам, а не нечто вроде огромного лог-файла, с которым неудобно работать.

В ходе исследования особое внимание уделялось наиболее часто встречающимся ошибкам. Для того чтобы такие ошибки отобрать, их ранжировали по количеству проектов разных компаний, в которых они встречаются. Если бы в этот рейтинг входило лишь общее число появлений некоей ошибки, то ошибки, характерные для какого-нибудь очень крупного проекта, но редко встречающиеся в других проектах, исказили бы результаты.

Вот десять ошибок, которые были отобраны по результатам исследования. Они отсортированы по количеству проектов, в которых они встречаются.

Ошибки, которые встречаются в JS-проектах чаще всего

Названия ошибок представляют собой сокращённый вариант сообщения об ошибке, которое выдаёт система. Опора на системные сообщения позволяет легко идентифицировать ошибки при их возникновении. Сейчас мы проанализируем каждую из них, расскажем о том, что их вызывает, и о том, как с ними бороться.

1. Uncaught TypeError: Cannot read property

Если вы пишете программы на JavaScript, то вы, вероятно, встречались с этой ошибкой гораздо чаще, чем вам того хотелось бы. Подобная ошибка возникает, например, в Google Chrome при попытке прочитать свойство или вызвать метод неопределённой переменной, то есть той, которая имеет значение undefined. Увидеть эту ошибку в действии можно с помощью консоли инструментов разработчика Chrome.

Ошибка Cannot read property

Эта ошибка может возникнуть по многим причинам, но чаще всего её вызывает неправильная инициализация состояния при рендеринге элемента пользовательского интерфейса. Взглянем на пример того, как подобное может произойти в реальном приложении. Тут мы используем React, но та же ошибка инициализации характерна для Angular, Vue и для любых других фреймворков.

class Quiz extends Component {
  componentWillMount() {
    axios.get('/thedata').then(res => {
      this.setState({items: res.data});
    });
  }

  render() {
    return (
      <ul>
        {this.state.items.map(item =>
          <li key={item.id}>{item.name}</li>
        )}
      </ul>
    );
  }
}

Тут надо обратить внимание на две важные вещи:

  1. В самом начале состояние компонента (то есть — this.state) представлено значением undefined.
  2. При асинхронной загрузке данных компонент будет выведен как минимум один раз до того, как данные будут загружены, вне зависимости от того, будет ли это выполнено в componentWillMount или в componentDidMount. Когда элемент Quiz выводится в первый раз, в this.state.items записано undefined. Это, в свою очередь, означает, что itemList получает элементы, которые так же представлены значением undefined. Как результат, мы видим в консоли следующую ошибку: "Uncaught TypeError: Cannot read property ‘map’ of undefined".

Эту ошибку исправить несложно. Проще всего инициализировать состояние в конструкторе подходящими значениями по умолчанию.

class Quiz extends Component {
  // Добавляем это:
  constructor(props) {
    super(props);

    // Инициализируем состояние и задаём значения элементов по умолчанию
    this.state = {
      items: []
    };
  }

  componentWillMount() {
    axios.get('/thedata').then(res => {
      this.setState({items: res.data});
    });
  }

  render() {
    return (
      <ul>
        {this.state.items.map(item =>
          <li key={item.id}>{item.name}</li>
        )}
      </ul>
    );
  }
}

Код вашего приложения будет выглядеть иначе, но мы надеемся, что теперь вы знаете, как исправить эту ошибку в своём проекте и как избежать её появления. Если то, о чём шла речь, вам не подходит — возможно, вам поможет разбор следующих ошибок.

2. TypeError: ‘undefined’ is not an object (evaluating…

Эта ошибка возникает в браузере Safari при попытке прочесть свойство или вызвать метод неопределённого объекта. Взглянуть на эту ошибку можно с помощью консоли инструментов разработчика Safari. На самом деле, тут перед нами та же самая проблема, которую мы разбирали выше для Chrome, но в Safari она приводит к другому сообщению об ошибке.

Ошибка ‘undefined’ is not an object

Исправлять эту ошибку надо так же, как в предыдущем примере.

3. TypeError: null is not an object (evaluating

Эта ошибка возникает в Safari при попытке обратиться к методу или свойству переменной, представленной значением null. Вот как это выглядит в консоли разработчика Safari.

Ошибка TypeError: null is not an object

Напомним, что в JavaScript null и undefined — это не одно и то же, именно поэтому мы видим разные сообщения об ошибках. Смысл значения undefined, записанного в переменную, говорит о том, что переменной не назначено никакого значения, а null указывает на пустое значение. Для того чтобы убедиться в том, что null не равно undefined, можно сравнить их с использованием оператора строгого равенства:

Сравнение undefined и null с помощью операторов нестрогого и строгого равенства

Одна из причин возникновения подобной ошибки в реальных приложениях заключается в попытке использования элемента DOM в JavaScript до загрузки элемента. Происходит это из-за того, что DOM API возвращает null для ссылок на пустые объекты.

Любой JS-код, который работает с элементами DOM, должен выполняться после создания элементов DOM. Интерпретация JS-кода производится сверху вниз по мере появления его в HTML-документе. Поэтому если тег <script> с программой окажется перед кодом, описывающим элементы DOM, программа будет выполнена в ходе разбора страницы до его завершения. Эта ошибка проявится, если элемент DOM, к которому обращаются из скрипта, не был создан до загрузки этого скрипта.

В следующем примере мы можем исправить проблему, добавив в код прослушиватель событий, который оповестит нас о том, что страница полностью загружена. После срабатывания обработчика события, добавленного с помощью addEventListener, метод init() сможет правильно работать с элементами DOM.

<script>
  function init() {
    var myButton = document.getElementById("myButton");
    var myTextfield = document.getElementById("myTextfield");
    myButton.onclick = function() {
      var userName = myTextfield.value;
    }
  }
  document.addEventListener('readystatechange', function() {
    if (document.readyState === "complete") {
      init();
    }
  });
</script>

<form>
  <input type="text" id="myTextfield" placeholder="Type your name" />
  <input type="button" id="myButton" value="Go" />
</form>

4. (unknown): Script error

Эта ошибка возникает в том случае, когда неперехваченная ошибка JavaScript пересекает границы доменов при нарушении политики кросс-доменных ограничений. Например, если ваш JS-код размещён на CDN-ресурсе, в сообщении о любой неперехваченной ошибке (то есть, об ошибке, которая не перехвачена в блоке try-catch и дошла до обработчика window.onerror) будет указано Script error, а не полезная для целей устранения этой ошибки информация. Это — один из браузерных механизмов безопасности, направленный на предотвращение передачи данных между фрагментами кода, источниками которого являются разные домены, и которым в обычных условиях запрещено обмениваться информацией.

Вот последовательность действий, которая поможет увидеть эту ошибку.

1. Отправка заголовка Access-Control-Allow-Origin.

Установка заголовка Access-Control-Allow-Origin в состояние * указывает на то, что к ресурсу можно получить доступ из любого домена.

Знак звёздочки можно, при необходимости, заменить на конкретный домен, например так: Access-Control-Allow-Origin: www.example.com. Однако поддержка нескольких доменов — дело довольно сложное. Такая поддержка может не стоить затраченных на её обеспечение усилий, если вы используете CDN, из-за возможного возникновения проблем с кэшированием. Подробности об этом можно посмотреть здесь.

Вот примеры установки этого заголовка в различных окружениях.

Apache

В папке, из которой будут загружаться ваши JavaScript-файлы, создайте файл .htaccess со следующим содержимым:

Header add Access-Control-Allow-Origin "*"

Nginx

Добавьте директиву add_header к блоку location, который отвечает за обслуживание ваших JS-файлов:

location ~ ^/assets/ {
    add_header Access-Control-Allow-Origin *;
}

HAProxy

Добавьте следующую настройку к параметрам системы, ответственной за поддержку JS-файлов:

rspadd Access-Control-Allow-Origin: *

2. Установите crossorigin="anonymous" в теге <script>.

В вашем HTML-файле для каждого из скриптов, для которого установлен заголовок Access-Control-Allow-Origin, установите crossorigin="anonymous" в теге <script>. Перед добавлением свойства crossorigin к тегу <script> проверьте отправку заголовка для файла скрипта. В Firefox, если атрибут crossorigin присутствует, а заголовок Access-Control-Allow-Origin — нет, скрипт выполнен не будет.

5. TypeError: Object doesn’t support property

Эта ошибка возникает в IE при попытке вызова неопределённого метода. Увидеть эту ошибку можно в консоли разработчика IE.

Ошибка Object doesn’t support property

Эта ошибка эквивалентна ошибке "TypeError: ‘undefined’ is not a function", которая возникает в Chrome. Обращаем ваше внимание на то, что речь идёт об одной и той же логической ошибке, о которой различные браузеры сообщают по-разному.

Это — обычная для IE проблема, возникающая в веб-приложениях, которые используют возможности пространств имён JavaScript. Когда возникает эта ошибка, то в 99.9% случаев её причиной является неспособность IE привязывать методы, расположенные в текущем пространстве имён, к ключевому слову this. Например, предположим, что имеется объект Rollbar с методом isAwesome. Обычно, находясь в пределах этого объекта, метод isAwesome можно вызвать так:

this.isAwesome();

Chrome, Firefox и Opera нормально воспримут такую команду. IE же её не поймёт. Таким образом, лучше всего, при использовании подобных конструкций, всегда предварять имя метода именем объекта (пространства имён), в котором он определён:

Rollbar.isAwesome();

6. TypeError: ‘undefined’ is not a function

Эта ошибка возникает в Chrome при попытке вызова неопределённой функции. Взглянуть на эту ошибку можно в консоли инструментов разработчика Chrome и в аналогичной консоли Firefox.

Ошибка TypeError: ‘undefined’ is not a function

Так как подходы к программированию на JavaScript и шаблоны проектирования постоянно усложняются, наблюдается и соответствующий рост числа ситуаций, в которых, внутри функций обратного вызова и замыканий, появляются области видимости, в которых используются ссылки на собственные методы и свойства с использованием ключевого слова this, что является довольно распространённым источником путаницы и ошибок.

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

function testFunction() {
  this.clearLocalStorage();
  this.timer = setTimeout(function() {
    this.clearBoard();    // что такое "this"?
  }, 0);
};

Выполнение вышеприведённого кода приведёт к следующей ошибке: "Uncaught TypeError: undefined is not a function." Причина появления этой ошибки заключается в том, что при вызове setTimeout() мы, на самом деле, вызываем window.setTimeout(). Как результат, анонимная функция, которая передаётся setTimeout(), оказывается определена в контексте объекта window, у которого нет метода clearBoard().

Традиционный подход к решению этой проблемы, совместимый со старыми версиями браузеров, заключается в том, чтобы просто сохранить ссылку на this в некоей переменной, к которой потом можно будет обратиться из замыкания. Например, это может выглядеть так:

function testFunction () {
  this.clearLocalStorage();
  var self = this;   // сохраним ссылку на 'this' пока оно является тем, чем мы его считаем!
  this.timer = setTimeout(function(){
    self.clearBoard();  
  }, 0);
};

В более современных браузерах можно использовать метод bind() для передачи необходимой ссылки:

function testFunction () {
  this.clearLocalStorage();
  this.timer = setTimeout(this.reset.bind(this), 0);  // осуществляем привязку к 'this'
};

function testFunction(){
    this.clearBoard();    //возвращаемся к контексту правильного 'this'!
};

7. Uncaught RangeError: Maximum call stack

У возникновения этой ошибки, например, в Chrome, есть несколько причин. Одна из них — бесконечный вызов рекурсивной функции. Вот как выглядит эта ошибка в консоли разработчика Chrome:

Ошибка Maximum call stack size exceeded

Подобное может произойти и в том случае, когда функции передают значение, находящееся за пределами некоего допустимого диапазона значений. Многие функции принимают лишь числа, находящиеся в определённом диапазоне. Например, функции Number.toExponential(digits) и Number.toFixed(digits) принимают аргумент digits, представленный числом от 0 до 20, а функция Number.toPrecision(digits) принимает числа от 1 до 21. Взглянем на ситуации, в которых вызов этих и некоторых других функций приводит к ошибкам:

var a = new Array(4294967295);  //OK
var b = new Array(-1); // ошибка!

var num = 2.555555;
document.writeln(num.toExponential(4));  //OK
document.writeln(num.toExponential(-2)); //ошибка!

num = 2.9999;
document.writeln(num.toFixed(2));   //OK
document.writeln(num.toFixed(25));  // ошибка!

num = 2.3456;
document.writeln(num.toPrecision(1));   //OK
document.writeln(num.toPrecision(22));  // ошибка!

8. TypeError: Cannot read property ‘length’

Эта ошибка возникает в Chrome при попытке прочесть свойство length переменной, в которую записано undefined. Взглянем на эту ошибку в консоли инструментов разработчика Chrome.

Ошибка Cannot read property ‘length’

Обычно, обращаясь к свойству length, узнают длину массивов, но вышеописанная ошибка может возникнуть если массив не инициализирован, или если имя переменной скрыто в области видимости, недоступной из того места, где к этой переменной пытаются обратиться. Для того чтобы лучше понять сущность этой ошибки, рассмотрим следующий пример:

var testArray= ["Test"];

function testFunction(testArray) {
    for (var i = 0; i < testArray.length; i++) {
      console.log(testArray[i]);
    }
}

testFunction();

При объявлении функции с параметрами эти параметры становятся для неё локальными переменными. В нашем примере это означает, что даже если в области видимости, окружающей функцию, есть переменная testArray, параметр с таким же именем скроет эту переменную и будет восприниматься как локальная переменная функции.

Для того чтобы решить эту проблему, в нашем случае можно пойти одним из следующих двух путей:

  1. Удаление параметра, заданного при объявлении функции (как видно из примера, мы хотим работать с помощью функции с массивом, который объявлен за её пределами, поэтому тут можно обойтись и без параметра функции):
    var testArray = ["Test"];
    
    /* Предварительное условие: определение testArray за пределами функции */
    function testFunction(/* без параметров */) {
        for (var i = 0; i < testArray.length; i++) {
          console.log(testArray[i]);
        }
    }
    
    testFunction();
  2. Вызов функции с передачей ей ранее объявленного массива:
    var testArray = ["Test"];
    
    function testFunction(testArray) {
       for (var i = 0; i < testArray.length; i++) {
          console.log(testArray[i]);
        }
    }
    
    testFunction(testArray);

9. Uncaught TypeError: Cannot set property

Когда мы пытаемся получить доступ к неопределённой переменной, то мы, фактически, работаем со значением типа undefined, а этот тип не поддерживает чтение или запись свойств. В подобном случае приложение выдаст следующую ошибку:

"Uncaught TypeError cannot set property of undefined."

Взглянем на неё в браузере Chrome.

Ошибка Cannot set property

Если объект test не существует, будет выдана ошибка "Uncaught TypeError cannot set property of undefined."

10. ReferenceError: event is not defined

Эта ошибка возникает при попытке получить доступ к неопределённой переменной, или к переменной, которая находится за пределами текущей области видимости. Взглянем на неё в консоли Chrome:

Ошибка ReferenceError: foo is not defined

Если вы сталкиваетесь с этой ошибкой при использовании системы обработки событий, убедитесь, что вы работаете с объектом события, переданным в качестве параметра. Более старые браузеры, вроде IE, предлагают глобальный доступ к событиям, но это не характерно для всех браузеров. Эту ситуацию пытаются исправить библиотеки вроде jQuery. В любом случае рекомендуется использовать именно тот объект события, которые передан в функцию обработки событий.

function myFunction(event) {
    event = event.which || event.keyCode;
    if(event.keyCode===13){
       alert(event.keyCode);
    }
}

Итоги

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

Уважаемые читатели! С какими JS-ошибками вы сталкивались в продакшне?

I have a currently fairly dysfunctional Javascript program that’s been causing me problems. However, it throws one error that I just don’t understand:

TypeError: 'undefined' is not an object (evaluating 'sub.from.length')

What I’m trying to do, as you can probably guess, is check the length of a certain «from» array in the sub dict. Here’s the source code for the entire function, and here’s the code of the loop that I think is causing the error:

console.log(afcHelper_ffuSubmissions.length); // just for debugging, returns the correct number
for (var i = 0; i < afcHelper_ffuSubmissions.length; i++) { // this whole section works fine
    var sub = afcHelper_ffuSubmissions[i];
    //console.log("THIS IS BROKEN DOWN BY LINK",afcHelper_Submissions[i]);
    if (pagetext.indexOf(afcHelper_ffuSections[sub.section]) == -1) {
        // Someone has modified the section in the mean time. Skip.
        document.getElementById('afcHelper_status').innerHTML += '<li>Skipping ' + sub.title + ': Cannot find section. Perhaps it was modified in the mean time?</li>';
        continue;
    }
    var text = afcHelper_ffuSections[sub.section];
    var startindex = pagetext.indexOf(afcHelper_ffuSections[sub.section]);
    var endindex = startindex + text.length;

    console.log(sub); 
    if (typeof(sub.from) != 'undefined' && sub.from.length > 0) { // ** problem spot?? this is the code i recently added.
        for (var i = 0; i < sub.from.length; i++) {
            mainid = sub.from[i]['id'];
            var sub = afcHelper_Submissions[mainid]; // and then it goes on from here...

Any ideas would be great. Frankly, I just can’t see why I’m getting a TypeError about something that I’ve already explicitly checked the type of (typeof(sub.from))…

mimo's user avatar

mimo

6,0317 gold badges41 silver badges47 bronze badges

asked Jul 18, 2013 at 6:27

user1483482's user avatar

7

I’m not sure how you could just check if something isn’t undefined and at the same time get an error that it is undefined. What browser are you using?

You could check in the following way (extra = and making length a truthy evaluation)

if (typeof sub !== 'undefined' && sub.from && sub.from.length) {

[update]

I see that you reset sub and thereby reset sub.from but fail to re check if sub.from exist:

for (var i = 0; i < sub.from.length; i++) {//<== assuming sub.from.exist
            mainid = sub.from[i]['id'];
            var sub = afcHelper_Submissions[mainid]; // <== re setting sub

My guess is that the error is not on the if statement but on the for(i... statement. In Firebug you can break automatically on an error and I guess it’ll break on that line (not on the if statement).

Mike 'Pomax' Kamermans's user avatar

answered Jul 18, 2013 at 6:42

HMR's user avatar

HMRHMR

37k24 gold badges89 silver badges160 bronze badges

8

try out this if you want to assign value to object and it is showing this error in angular..

crate object in construtor

this.modelObj = new Model(); //<———- after declaring object above

Arghya Sadhu's user avatar

Arghya Sadhu

40.2k9 gold badges77 silver badges107 bronze badges

answered Aug 28, 2020 at 7:12

Cani vasa's user avatar

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

От автора: чтобы вернуть сообщество разработчиков, мы рассмотрели нашу базу данных по тысячам проектов и нашли 10 самых распространённых ошибок в JavaScript. Мы собираемся показать вам, что к ним приводит и как это предотвратить. Если ни одна ошибка JavaScript не встречается в вашем коде, это делает вас лучшим разработчиком.

Поскольку всем управляют данные, мы собрали, проанализировали и оценили первые 10 ошибок JavaScript. Rollbar собирает все ошибки из каждого проекта и суммирует, сколько раз каждая из них возникала. Мы делаем это, группируя ошибки в соответствии с их отпечатками пальцев . В принципе, группируется по две ошибки, если вторая — это просто повторение первой. Это дает пользователям хороший обзор вместо огромной свалки, какую вы видели в файле журнала.

Мы сосредоточились на ошибках, которые скорее всего повлияют на вас и ваших пользователей. Чтобы сделать это, мы оценили ошибки по количеству проектов, испытывающихся в разных компаниях. Если бы мы посмотрели только на общее количество раз, когда произошла каждая ошибка, то клиенты большого объема могли бы подавить набор данных с ошибками, которые не имеют отношения к большинству читателей.

Вот первые 10 ошибок JavaScript:

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Профессия Frontend-разработчик PRO

Готовим Frontend-разработчиков с нуля

На курсе вы научитесь создавать интерфейсы веб-сервисов с помощью языков программирования и
дополнительных технологий. Сможете разрабатывать планировщики задач, мессенджеры, интернет-магазины…

Узнать подробнее

До 10 проектов в портфолио для старта карьеры

Подходит для новичков без опыта в программировании

Практика на вебинарах с разработчиками из крупных компаний

Ошибки были сокращены для удобства чтения. Давайте погрузимся глубже в каждую, чтобы определить, что может вызвать её, и как избежать их появления.

1. Uncaught TypeError: Cannot read property

Если вы разработчик JavaScript, то, вероятно, видели эту ошибку очень много раз. Это происходит в Chrome, когда вы читаете свойство или вызываете метод на неопределенный объект. Это можно очень легко проверить в консоли разработчика Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Это может произойти по многим причинам, но чаще всего это неправильная инициализация состояния при рендеринге компонентов пользовательского интерфейса. Давайте рассмотрим пример того, как это может произойти в реальном приложении. Мы выберем React, но те же принципы неправильной инициализации применимы и к Angular, Vue или любой другой структуре.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class Quiz extends Component {

  componentWillMount() {

    axios.get(‘/thedata’).then(res => {

      this.setState({items: res.data});

    });

  }

  render() {

    return (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

Здесь понимаются две важные вещи:

Состояние компонента (например, this.state ) начинает жизнь как undefined.

Когда вы извлекаете данные асинхронно, компонент будет отображаться как минимум один раз перед загрузкой данных — независимо от того, выбрана ли она в конструкторе componentWillMount или componentDidMount . Когда Quiz отображается впервые, this.state.items не определен. Это, в свою очередь, означает, что ItemList получает элементы как неопределенные, и вы получаете сообщение об ошибке «Uncaught TypeError: Невозможно прочитать карту свойств» в консоли.

Это легко исправить. Самый простой способ: инициализировать состояние с разумными значениями по умолчанию в конструкторе.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

class Quiz extends Component {

  // Added this:

  constructor(props) {

    super(props);

    // Assign state itself, and a default value for items

    this.state = {

      items: []

    };

  }

  componentWillMount() {

    axios.get(‘/thedata’).then(res => {

      this.setState({items: res.data});

    });

  }

  render() {

    return (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

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

2. TypeError: ‘undefined’ is not an object (evaluating

Эта ошибка возникает в Safari при чтении свойства или вызове метода для неопределенного объекта. Вы можете проверить это в консоли разработчика Safari. Это по сути то же самое, что и вышеприведенная ошибка для Chrome, только Safari использует другое сообщение об ошибке.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Профессия Frontend-разработчик PRO

Готовим Frontend-разработчиков с нуля

На курсе вы научитесь создавать интерфейсы веб-сервисов с помощью языков программирования и
дополнительных технологий. Сможете разрабатывать планировщики задач, мессенджеры, интернет-магазины…

Узнать подробнее

До 10 проектов в портфолио для старта карьеры

Подходит для новичков без опыта в программировании

Практика на вебинарах с разработчиками из крупных компаний

Ошибки были сокращены для удобства чтения. Давайте погрузимся глубже в каждую, чтобы определить, что может вызвать её, и как избежать их появления.

1. Uncaught TypeError: Cannot read property

Если вы разработчик JavaScript, то, вероятно, видели эту ошибку очень много раз. Это происходит в Chrome, когда вы читаете свойство или вызываете метод на неопределенный объект. Это можно очень легко проверить в консоли разработчика Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Это может произойти по многим причинам, но чаще всего это неправильная инициализация состояния при рендеринге компонентов пользовательского интерфейса. Давайте рассмотрим пример того, как это может произойти в реальном приложении. Мы выберем React, но те же принципы неправильной инициализации применимы и к Angular, Vue или любой другой структуре.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class Quiz extends Component {

  componentWillMount() {

    axios.get(‘/thedata’).then(res => {

      this.setState({items: res.data});

    });

  }

  render() {

    return (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

Здесь понимаются две важные вещи:

Состояние компонента (например, this.state ) начинает жизнь как undefined.

Когда вы извлекаете данные асинхронно, компонент будет отображаться как минимум один раз перед загрузкой данных — независимо от того, выбрана ли она в конструкторе componentWillMount или componentDidMount . Когда Quiz отображается впервые, this.state.items не определен. Это, в свою очередь, означает, что ItemList получает элементы как неопределенные, и вы получаете сообщение об ошибке «Uncaught TypeError: Невозможно прочитать карту свойств» в консоли.

Это легко исправить. Самый простой способ: инициализировать состояние с разумными значениями по умолчанию в конструкторе.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

class Quiz extends Component {

  // Added this:

  constructor(props) {

    super(props);

    // Assign state itself, and a default value for items

    this.state = {

      items: []

    };

  }

  componentWillMount() {

    axios.get(‘/thedata’).then(res => {

      this.setState({items: res.data});

    });

  }

  render() {

    return (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

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

2. TypeError: ‘undefined’ is not an object (evaluating

Эта ошибка возникает в Safari при чтении свойства или вызове метода для неопределенного объекта. Вы можете проверить это в консоли разработчика Safari. Это по сути то же самое, что и вышеприведенная ошибка для Chrome, только Safari использует другое сообщение об ошибке.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

3. TypeError: null is not an object (evaluating

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

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Интересно, что в JavaScript значения null и undefined не совпадают, поэтому мы видим два разных сообщения об ошибках. Undefined обычно является переменной, которая не была назначена, а null означает, что значение пустое. Чтобы убедиться, что они не одно и то же, попробуйте использовать строгий оператор равенства:

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Один из способов, которым эта ошибка может возникнуть в реальном мире — это попытка использовать элемент DOM в JavaScript перед загрузкой элемента. Это потому, что DOM API возвращает null для ссылок на пустые объекты.

Любой JS-код, который выполняет и обрабатывает элементы DOM, должен выполняться после создания элементов DOM. JS-код интерпретируется сверху вниз, как изложено в HTML. Итак, если перед элементами DOM есть тег, код JS в теге скрипта будет выполняться, когда браузер анализирует HTML-страницу. Вы получите эту ошибку, если элементы DOM не были созданы до загрузки сценария.

В этом примере мы можем решить проблему, добавив прослушиватель событий, который уведомит нас, когда страница будет готова. После addEventListener метод init() может использовать элементы DOM.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<script>

  function init() {

    var myButton = document.getElementById(«myButton»);

    var myTextfield = document.getElementById(«myTextfield»);

    myButton.onclick = function() {

      var userName = myTextfield.value;

    }

  }

  document.addEventListener(‘readystatechange’, function() {

    if (document.readyState === «complete») {

      init();

    }

  });

</script>

<form>

  <input type=«text» id=«myTextfield» placeholder=«Type your name» />

  <input type=«button» id=«myButton» value=«Go» />

</form>

4. (unknown): Script error

Ошибка скрипта возникает, когда ошибка неперехваченного JavaScript пересекает границы домена и нарушает политику перекрестного происхождения. Например, если вы размещаете свой код JavaScript на CDN, любые неперехваченные ошибки (ошибки, которые появляются в обработчике window.onerror, вместо того, чтобы быть пойманным в try-catch) будут переданы как просто «Script error» вместо того, чтобы содержать полезную информацию. Эта мера безопасности браузера предназначена для предотвращения передачи данных по доменам, которые в противном случае не были бы допущены к коммуникации.

Чтобы получить реальные сообщения об ошибках, выполните следующие действия:

1. Отправьте заголовок Access-Control-Allow-Origin

Установка заголовка Access-Control-Allow-Origin в * означает, что к ресурсу можно получить доступ из любого домена. Вы можете заменить * своим доменом, если необходимо: например, Access-Control-Allow-Origin: www.example.com . Если вы используете CDN из-за проблем с кэшированием, которые могут возникнуть, обработка нескольких доменов становится сложной и нельзя не приложить усилий. Подробнее см. здесь.

Вот несколько примеров того, как установить этот заголовок в различных средах:

Apache

В папках, где будут храниться ваши файлы JavaScript, создайте файл .htaccess со следующим содержимым:

Header add AccessControlAllowOrigin «*»

Nginx

Добавьте директиву add_header в блок местоположения, который служит файлам JavaScript:

location ~ ^/assets/ { add_header AccessControlAllowOrigin *; }

HAProxy

Добавьте в ресурс, где будут загружены файлы JavaScript:

rspadd AccessControlAllowOrigin: *

2. Установите crossorigin = «anonymous» в теге скрипта

В HTML-источнике для каждого из сценариев, где вы установите заголовок Access-Control-Allow-Origin, в теге SCRIPT установите crossorigin=»anonymous». Убедитесь, что заголовок отправляется для файла сценария, перед добавлением свойства crossorigin в тег скрипта. В Firefox, если атрибут crossorigin присутствует, но заголовок Access-Control-Allow-Origin отсутствует, сценарий не будет выполнен.

5. TypeError: Object doesn’t support property

Это ошибка, которая возникает в IE при вызове неопределенного метода. Вы можете проверить это в IE Developer Console.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Это эквивалентно ошибке «TypeError: ‘undefined’ is not a function» в Chrome. Да, разные браузеры могут иметь разные сообщения для одной и той же ошибки.

Это обычная проблема для IE в веб-приложениях, использующих пространство имен JavaScript. Когда это так, проблема в 99,9% случаев— это неспособность IE связать методы в текущем пространстве имен с ключевым словом this. Например, если у вас есть пространство имен имен Rollbar с помощью метода isAwesome. Обычно, если вы находитесь в пространстве имен Rollbar вы можете вызвать метод isAwesome со следующим синтаксисом:

Chrome, Firefox и Opera с радостью согласятся с этим синтаксисом. С другой стороны, IE не станет. Таким образом, самая безопасная ставка при использовании JS namespacing — это префикс с фактическим пространством имен.

6. TypeError: ‘undefined’ is not a function

Это ошибка, возникающая в Chrome при вызове неопределенной функции. Вы можете протестировать это в консоли разработчика Chrome и в Mozilla Firefox.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Поскольку на протяжении многих лет методы кодирования JavaScript и шаблоны проектирования становятся все более изощренными, наблюдается соответствующее увеличение распространения областей самореференции в обратных вызовах и закрытиях, которые являются довольно распространенным источником этой путаницы.

Рассмотрим фрагмент кода:

function clearBoard(){

  alert(«Cleared»);

}

document.addEventListener(«click», function(){

  this.clearBoard(); // what is “this” ?

});

Выполнение вышеуказанного кода приводит к следующей ошибке: «Uncaught TypeError: undefined is not function». Причина, по которой вы получаете эту ошибку, заключается в том, что при вызове setTimeout() вы вызываете window.setTimeout(). В результате анонимная функция, передаваемая setTimeout(), определяется в контексте объекта окна, у которого нет clearBoard().

Традиционное решение, совместимое со старым браузером — просто сохранить ссылку на this в переменной, которая затем может быть унаследована закрытием. Например:

var self=this;  // save reference to ‘this’, while it’s still this!

document.addEventListener(«click», function(){

  self.clearBoard();

});

Кроме того, в новых браузерах для передачи правильной ссылки вы можете использовать метод bind():

document.addEventListener(«click»,this.clearBoard.bind(this));

7. Uncaught RangeError: Maximum call stack

Это ошибка, которая возникает в Chrome при нескольких обстоятельствах. Одно из них — когда вы вызываете рекурсивную функцию, которая не завершается. Вы можете протестировать это в консоли разработчика Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Один из способов, которым эта ошибка может возникнуть в реальном мире — это попытка использовать элемент DOM в JavaScript перед загрузкой элемента. Это потому, что DOM API возвращает null для ссылок на пустые объекты.

Любой JS-код, который выполняет и обрабатывает элементы DOM, должен выполняться после создания элементов DOM. JS-код интерпретируется сверху вниз, как изложено в HTML. Итак, если перед элементами DOM есть тег, код JS в теге скрипта будет выполняться, когда браузер анализирует HTML-страницу. Вы получите эту ошибку, если элементы DOM не были созданы до загрузки сценария.

В этом примере мы можем решить проблему, добавив прослушиватель событий, который уведомит нас, когда страница будет готова. После addEventListener метод init() может использовать элементы DOM.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<script>

  function init() {

    var myButton = document.getElementById(«myButton»);

    var myTextfield = document.getElementById(«myTextfield»);

    myButton.onclick = function() {

      var userName = myTextfield.value;

    }

  }

  document.addEventListener(‘readystatechange’, function() {

    if (document.readyState === «complete») {

      init();

    }

  });

</script>

<form>

  <input type=«text» id=«myTextfield» placeholder=«Type your name» />

  <input type=«button» id=«myButton» value=«Go» />

</form>

4. (unknown): Script error

Ошибка скрипта возникает, когда ошибка неперехваченного JavaScript пересекает границы домена и нарушает политику перекрестного происхождения. Например, если вы размещаете свой код JavaScript на CDN, любые неперехваченные ошибки (ошибки, которые появляются в обработчике window.onerror, вместо того, чтобы быть пойманным в try-catch) будут переданы как просто «Script error» вместо того, чтобы содержать полезную информацию. Эта мера безопасности браузера предназначена для предотвращения передачи данных по доменам, которые в противном случае не были бы допущены к коммуникации.

Чтобы получить реальные сообщения об ошибках, выполните следующие действия:

1. Отправьте заголовок Access-Control-Allow-Origin

Установка заголовка Access-Control-Allow-Origin в * означает, что к ресурсу можно получить доступ из любого домена. Вы можете заменить * своим доменом, если необходимо: например, Access-Control-Allow-Origin: www.example.com . Если вы используете CDN из-за проблем с кэшированием, которые могут возникнуть, обработка нескольких доменов становится сложной и нельзя не приложить усилий. Подробнее см. здесь.

Вот несколько примеров того, как установить этот заголовок в различных средах:

Apache

В папках, где будут храниться ваши файлы JavaScript, создайте файл .htaccess со следующим содержимым:

Header add AccessControlAllowOrigin «*»

Nginx

Добавьте директиву add_header в блок местоположения, который служит файлам JavaScript:

location ~ ^/assets/ { add_header AccessControlAllowOrigin *; }

HAProxy

Добавьте в ресурс, где будут загружены файлы JavaScript:

rspadd AccessControlAllowOrigin: *

2. Установите crossorigin = «anonymous» в теге скрипта

В HTML-источнике для каждого из сценариев, где вы установите заголовок Access-Control-Allow-Origin, в теге SCRIPT установите crossorigin=»anonymous». Убедитесь, что заголовок отправляется для файла сценария, перед добавлением свойства crossorigin в тег скрипта. В Firefox, если атрибут crossorigin присутствует, но заголовок Access-Control-Allow-Origin отсутствует, сценарий не будет выполнен.

5. TypeError: Object doesn’t support property

Это ошибка, которая возникает в IE при вызове неопределенного метода. Вы можете проверить это в IE Developer Console.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Это эквивалентно ошибке «TypeError: ‘undefined’ is not a function» в Chrome. Да, разные браузеры могут иметь разные сообщения для одной и той же ошибки.

Это обычная проблема для IE в веб-приложениях, использующих пространство имен JavaScript. Когда это так, проблема в 99,9% случаев— это неспособность IE связать методы в текущем пространстве имен с ключевым словом this. Например, если у вас есть пространство имен имен Rollbar с помощью метода isAwesome. Обычно, если вы находитесь в пространстве имен Rollbar вы можете вызвать метод isAwesome со следующим синтаксисом:

Chrome, Firefox и Opera с радостью согласятся с этим синтаксисом. С другой стороны, IE не станет. Таким образом, самая безопасная ставка при использовании JS namespacing — это префикс с фактическим пространством имен.

6. TypeError: ‘undefined’ is not a function

Это ошибка, возникающая в Chrome при вызове неопределенной функции. Вы можете протестировать это в консоли разработчика Chrome и в Mozilla Firefox.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Поскольку на протяжении многих лет методы кодирования JavaScript и шаблоны проектирования становятся все более изощренными, наблюдается соответствующее увеличение распространения областей самореференции в обратных вызовах и закрытиях, которые являются довольно распространенным источником этой путаницы.

Рассмотрим фрагмент кода:

function clearBoard(){

  alert(«Cleared»);

}

document.addEventListener(«click», function(){

  this.clearBoard(); // what is “this” ?

});

Выполнение вышеуказанного кода приводит к следующей ошибке: «Uncaught TypeError: undefined is not function». Причина, по которой вы получаете эту ошибку, заключается в том, что при вызове setTimeout() вы вызываете window.setTimeout(). В результате анонимная функция, передаваемая setTimeout(), определяется в контексте объекта окна, у которого нет clearBoard().

Традиционное решение, совместимое со старым браузером — просто сохранить ссылку на this в переменной, которая затем может быть унаследована закрытием. Например:

var self=this;  // save reference to ‘this’, while it’s still this!

document.addEventListener(«click», function(){

  self.clearBoard();

});

Кроме того, в новых браузерах для передачи правильной ссылки вы можете использовать метод bind():

document.addEventListener(«click»,this.clearBoard.bind(this));

7. Uncaught RangeError: Maximum call stack

Это ошибка, которая возникает в Chrome при нескольких обстоятельствах. Одно из них — когда вы вызываете рекурсивную функцию, которая не завершается. Вы можете протестировать это в консоли разработчика Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Это также может произойти, если вы передадите значение функции, находящейся за пределами допустимого диапазона. Многие функции принимают только определенный диапазон чисел для своих входных значений. Например, Number.toExponential(digits) и N umber.toFixed(digits) принимают цифры от 0 до 20, а Number.toPrecision(digits) принимают цифры от 1 до 21.

var a = new Array(4294967295);  //OK

var b = new Array(1); //range error

var num = 2.555555;

document.writeln(num.toExponential(4));  //OK

document.writeln(num.toExponential(2)); //range error!

num = 2.9999;

document.writeln(num.toFixed(2));   //OK

document.writeln(num.toFixed(25));  //range error!

num = 2.3456;

document.writeln(num.toPrecision(1));   //OK

document.writeln(num.toPrecision(22));  //range error!

8. TypeError: Cannot read property ‘length’

Это ошибка, которая возникает в Chrome из-за свойства длины чтения для неопределенной переменной. Вы можете протестировать это в консоли разработчика Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Обычно вы определяете длину, определенную в массиве, но вы можете столкнуться с этой ошибкой, если массив не инициализирован или если имя переменной скрыто в другом контексте. Давайте рассмотрим эту ошибку на следующем примере.

var testArray= [«Test»];

function testFunction(testArray) {

    for (var i = 0; i < testArray.length; i++) {

      console.log(testArray[i]);

    }

}

testFunction();

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

У вас есть два способа решить эту проблему:

1. Удалите параметры в объявлении функции (оказывается, вы хотите получить доступ к тем переменным, которые объявлены вне функции, поэтому вам не нужны параметры для вашей функции):

var testArray = [«Test»];

/* Precondition: defined testArray outside of a function */

function testFunction(/* No params */) {

    for (var i = 0; i < testArray.length; i++) {

      console.log(testArray[i]);

    }

}

testFunction();

2. Вызовите функцию, передав ей массив, который мы объявили:

var testArray = [«Test»];

function testFunction(testArray) {

   for (var i = 0; i < testArray.length; i++) {

      console.log(testArray[i]);

    }

}

testFunction(testArray);

9. Uncaught TypeError: Cannot set property

Когда мы пытаемся получить доступ к неопределенной переменной, она всегда возвращает undefined, а мы не можем получить или установить любое свойство undefined. В этом случае приложение будет выбрасывать “Uncaught TypeError cannot set property of undefined.”

Например, в браузере Chrome:

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Если объект test не существует, будет выдаваться ошибка: “Uncaught TypeError cannot set property of undefined.”

10. ReferenceError: event is not defined

Эта ошибка возникает при попытке получить доступ к переменной, которая не определена или находится за пределами текущей области. Вы можете легко протестировать её в браузере Chrome.

Топ-10 ошибок JavaScript из 1000+ проектов (и как их избежать)

Если вы получаете эту ошибку при использовании системы обработки событий, убедитесь, что вы используете объект события, переданный в качестве параметра. Старые браузеры, такие как IE, предлагают событие глобальной переменной, но не поддерживаются во всех браузерах. Библиотеки, подобные jQuery, пытаются нормализовать это поведение. Тем не менее, лучше использовать тот объект, который передается в функцию обработчика событий.

document.addEventListener(«mousemove», function (event) {

  console.log(event);

})

Вывод

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

Rollbar предлагает уникальные возможности для приложений JavaScript, таких как телеметрия, которые сообщают вам, что произошло в браузере пользователя, что приводит к ошибке. Это прозрение, которого у вас нет за пределами локальной консоли разработчика.

Автор: Jason Skowronski

Источник: //rollbar.com/

Профессия Frontend-разработчик PRO

Готовим Frontend-разработчиков с нуля

На курсе вы научитесь создавать интерфейсы веб-сервисов с помощью языков программирования и
дополнительных технологий. Сможете разрабатывать планировщики задач, мессенджеры, интернет-магазины…

Узнать подробнее

До 10 проектов в портфолио для старта карьеры

Подходит для новичков без опыта в программировании

Практика на вебинарах с разработчиками из крупных компаний

Редакция: Команда webformyself.

When working with JavaScript, you may encounter the error message «undefined is not an object (evaluating)» at some point. This error occurs when you try to access a property or call a method on an object that is undefined. In this guide, we will walk you through the process of identifying and fixing this error.

Table of Contents

  • Understanding the Error
  • Common Causes
  • Step-by-Step Solutions
  • Check for Typos
  • Ensure Proper Initialization
  • Use Optional Chaining
  • Check for Asynchronous Code Execution
  • FAQs

Understanding the Error

Before diving into the solutions, it’s essential to have a clear understanding of what this error message means. «undefined is not an object (evaluating)» indicates that you’re trying to access a property or method of an undefined variable, which is not possible in JavaScript.

For example, if you have the following code:

const person = {
  name: 'John',
  age: 30,
};
console.log(person.job.title);

You will get the error message because person.job is undefined, and you’re trying to access the title property of an undefined object.

Common Causes

There are several common scenarios that can lead to this error:

  1. Typos in variable names or object properties
  2. Attempting to access a property of an object that hasn’t been initialized yet
  3. Trying to access a property from a result of an asynchronous operation that hasn’t completed yet

Step-by-Step Solutions

Check for Typos

The first step in troubleshooting this error is to carefully review your code for any typos in variable names or object properties. In many cases, a simple typo can lead to an undefined object, causing the error.

Ensure Proper Initialization

Make sure that the object you’re trying to access is properly initialized before attempting to access its properties or methods. If the object is created conditionally, ensure that the condition is met before accessing its properties.

For example, if you have the following code:

let person;
if (someCondition) {
  person = {
    name: 'John',
    age: 30,
  };
}
console.log(person.name);

You will get the error if someCondition is false because person will remain undefined. To fix this, you can add a default value for person:

let person = {
  name: '',
  age: 0,
};
if (someCondition) {
  person = {
    name: 'John',
    age: 30,
  };
}
console.log(person.name);

Use Optional Chaining

Optional chaining (introduced in ECMAScript 2020) allows you to access properties of an object without throwing an error if the object is undefined. To use optional chaining, add a ?. before the property you want to access.

For example, if you have the following code:

const person = {
  name: 'John',
  age: 30,
};
console.log(person.job?.title);

In this case, console.log(person.job?.title) will not throw an error even if person.job is undefined. Instead, it will return undefined.

Check for Asynchronous Code Execution

If the object you’re trying to access is created or modified as a result of an asynchronous operation (e.g., fetching data from an API), make sure that you’re accessing the object’s properties after the operation has completed.

For example, if you have the following code:

let person;
fetch('https://api.example.com/person')
  .then((response) => response.json())
  .then((data) => {
    person = data;
  });
console.log(person.name);

You will get the error because person is still undefined when you try to access person.name. To fix this, move the console.log statement inside the .then() block:

let person;
fetch('https://api.example.com/person')
  .then((response) => response.json())
  .then((data) => {
    person = data;
    console.log(person.name);
  });

FAQs

What does «undefined is not an object (evaluating)» mean? {#faqs}

This error message means that you’re trying to access a property or method of an undefined variable in JavaScript.

How can I prevent this error from occurring?

You can prevent this error by making sure the object you’re trying to access is properly initialized and by using optional chaining when accessing properties of objects that might be undefined.

What is optional chaining?

Optional chaining is a feature introduced in ECMAScript 2020 that allows you to access properties of an object without throwing an error if the object is undefined. To use optional chaining, add a ?. before the property you want to access.

How do I know if my code is executing asynchronously?

If your code involves callbacks, promises, or async/await, it’s likely executing asynchronously. Make sure to access the properties of objects created or modified in asynchronous operations only after the operation has completed.

How can typos cause the «undefined is not an object (evaluating)» error?

A typo in a variable name or object property can cause the variable to be undefined, leading to this error. Double-check your code for typos to help prevent this error.

Related articles:

  • Understanding JavaScript Optional Chaining
  • Working with Asynchronous JavaScript
  • JavaScript Promises: An Introduction

I had the same issue using Typescript but I made it work,

I first created an object type with mappings for each route name, I did that on App.tsx

export type RootStackParamList = {
  Challenges: undefined
  AudioLesson: undefined
}

Then used that type when using createNativeStackNavigator

const Stack = createNativeStackNavigator<RootStackParamList>()

On a screen, ‘Challenges’ in my example, I created an object type for it

export type ChallengesType = NativeStackScreenProps<RootStackParamList, 'Challenges'>

I used that type in the screen like so

export default function Challenges({ navigation }: ChallengesType) {

Then I passed the navigation object to the final component that will be using it like this:

        <SomeComponent button_title="Tap me" navigation={navigation} />

And the part I somehow managed to get right was this:
In the component, create an object type and include navigation, as the type for it put the object type of the Screen you are coming from ( navigation: ChallengesType[‘navigation’] for example).

You can also use multiple screen types here to use the component in more screens. ( navigation: AudioLessonType[‘navigation’] | ChallengesType[‘navigation’]
)

import React from 'react'
import { Button } from 'react-native'
import { ChallengesType } from 'src/Challenges'

interface SomeComponentType {
  button_title: string
  navigation: ChallengesType['navigation']
}

export default function SomeComponent(params: SomeComponentType) {
  const { button_title, navigation } = params

  return <Button title={button_title} onPress={() => navigation.navigate('AudioLesson')} />
}

Понравилась статья? Поделить с друзьями:
  • Ошибка unb на стиральной машине haier как исправить ошибку
  • Ошибка undefined error код ошибки 0
  • Ошибка unauthorized код ошибки 401
  • Ошибка undefined array key php
  • Ошибка unark dll вернул код ошибки 1