Cannot read properties of undefined (reading 'length')
  • 14-May-2023
Lightrun Team
Author Lightrun Team
Share
Cannot read properties of undefined (reading 'length')

Cannot read properties of undefined (reading ‘length’)

Lightrun Team
Lightrun Team
14-May-2023

Explanation of the problem

The problem occurs in a Vue 3 application using Vue CLI version 4.5, CodeMirror version 5.63.3, and the Chrome browser version 93.0.4577.82 (x86_64). The issue arises when switching the CodeMirror (CM) editor from a small window mode to fullscreen. Upon clicking anywhere in the fullscreen mode, an exception message is thrown in the browser console tab. The exception message specifically points to the mapFromLineView function in the codemirror.js file, indicating a TypeError where properties of undefined (specifically ‘length’) cannot be read. Here is the relevant code snippet where the exception is triggered:

function mapFromLineView(lineView, line, lineN) {
    if (lineView.line == line) {
        return {map: lineView.measure.map, cache: lineView.measure.cache};
    }
    for (var i = 0; i < lineView.rest.length; i++) {
        if (lineView.rest[i] == line) {
            return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
        }
    }
    for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) {
        if (lineNo(lineView.rest[i$1]) > lineN) {
            return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true};
        }
    }
}

The exception occurs when executing the second for loop within the mapFromLineView method. The lineView.rest array is undefined, causing the error to be thrown when trying to access its length property. This leads to the “Uncaught TypeError: Cannot read properties of undefined (reading ‘length’)” exception being displayed in the browser console. It’s worth noting that every click anywhere within the fullscreen CM editor triggers the same exception.

Troubleshooting with the Lightrun Developer Observability Platform

Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.

  • Instantly add logs to, set metrics in, and take snapshots of live applications
  • Insights delivered straight to your IDE or CLI
  • Works where you do: dev, QA, staging, CI/CD, and production

Start for free today

Problem solution for Cannot read properties of undefined (reading ‘length’)

To resolve this issue, it is necessary to ensure that the lineView.rest array is defined before attempting to access its properties. One possible solution would be to add a check to verify the existence of lineView.rest before executing the for loop. Here’s an updated code snippet illustrating the suggested modification:

function mapFromLineView(lineView, line, lineN) {
    if (lineView.line == line) {
        return {map: lineView.measure.map, cache: lineView.measure.cache};
    }
    if (lineView.rest && lineView.rest.length) {
        for (var i = 0; i < lineView.rest.length; i++) {
            if (lineView.rest[i] == line) {
                return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
            }
        }
    }
    for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) {
        if (lineNo(lineView.rest[i$1]) > lineN) {
            return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true};
        }
    }
}

By including the if (lineView.rest && lineView.rest.length) condition, the code ensures that the second for loop is only executed when lineView.rest is defined and has a non-zero length. This modification prevents the “TypeError” exception from occurring when lineView.rest is undefined. Applying this fix should resolve the issue and prevent the exception from being thrown when clicking anywhere in the fullscreen CM editor.

Other popular problems with JedWatson React Codemirror

Problem: ReferenceError: “navigator” is not defined

This error occurs when trying to import and render the ‘JedWatson React Codemirror’ component. It is because ‘navigator’ is not defined in the Node environment, but it is available in the browser environment.

Solution:

The solution is to conditionally import the component and modules and check if certain objects are defined. For example:

let CodeMirror = null;
if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined') {
  CodeMirror = require('react-codemirror');
  require('codemirror/mode/yaml/yaml');
  require('codemirror/mode/dockerfile/dockerfile');
}

And then render the component with the condition:

// render
   { CodeMirror && <CodeMirror ... /> }

Problem: Compatibility issues with NextJS

When using NextJS, server-side rendering (SSR) can cause issues with the ‘JedWatson React Codemirror’ component. This is because the component relies on certain browser APIs that are not available in the Node environment.

Solution:

The solution is to use the ‘dynamic’ component provided by NextJS and set the ‘ssr’ property to ‘false’:

import dynamic from 'next/dynamic'; 
const CodeMirror = dynamic(() => import('react-codemirror'), { ssr: false });

Problem: Inefficient Rendering

In some cases, the ‘JedWatson React Codemirror’ component can cause slow rendering times, especially when dealing with large amounts of code or data. This can negatively impact the performance of the entire application.

Solution:

The solution is to optimize the rendering process by using the ‘shouldComponentUpdate’ lifecycle method to avoid unnecessary renderings and only render when there are actual changes to the component’s state. Additionally, the ‘key’ property can be used to ensure that the component only re-renders when the code or data changes:

class CodeEditor extends React.Component {
  shouldComponentUpdate(nextProps) {
    return nextProps.value !== this.props.value;
  }

  render() {
    return (
      <CodeMirror
        key={this.props.value}
        value={this.props.value}
        onChange={this.props.onChange}
      />
    );
  }
}

A brief introduction to JedWatson React Codemirror

JedWatson React Codemirror is a library that provides a React component for using the CodeMirror code editor in React applications. The library allows developers to easily integrate a feature-rich code editor into their projects without having to worry about managing the complexities of the underlying CodeMirror library.

The library provides a number of useful features for the code editor, such as syntax highlighting, line numbering, and the ability to set custom themes. It also supports a number of customization options that allow developers to modify the behavior and appearance of the editor to suit their needs. This includes options for controlling the size and position of the editor, as well as support for adding custom keybindings and customizing the context menu.

Most popular use cases for JedWatson React Codemirror

  1. Text Editing: JedWatson React Codemirror provides a text editing component for web applications, allowing users to create and edit source code, rich text, and other text-based content with syntax highlighting, line numbering, and more.
  2. Code Highlighting: The component supports a wide range of programming languages, providing accurate syntax highlighting for each language. This can be seen in the code block below where JavaScript code is rendered with syntax highlighting in the Codemirror component:
import React, { useState } from "react";
import Codemirror from "react-codemirror";

const App = () => {
  const [code, setCode] = useState("// type your code here");
  return (
    <Codemirror
      value={code}
      onChange={setCode}
      options={{
        mode: "javascript",
        lineNumbers: true,
      }}
    />
  );
};

export default App;
  1. Customization: JedWatson React Codemirror provides a rich set of customization options, including key bindings, themes, line wrapping, and more. This allows developers to tailor the component to the specific needs of their applications, providing a more seamless user experience.
Share

It’s Really not that Complicated.

You can actually understand what’s going on inside your live applications.

Try Lightrun’s Playground

Lets Talk!

Looking for more information about Lightrun and debugging?
We’d love to hear from you!
Drop us a line and we’ll get back to you shortly.

By submitting this form, I agree to Lightrun’s Privacy Policy and Terms of Use.