Issue with Vue/Nuxt 3: Unable to modify properties of null when setting 'textContent'

I am currently facing an issue with a function that is designed to switch words every few seconds. The functionality itself is working fine, but I keep encountering the following error intermittently in the VSC console:

TypeError: Cannot set properties of null (setting 'textContent') at Timeout._onTimeout (.../components/home/Hero.vue:36:28) at listOnTimeout (node:internal/timers:564:17)

It's puzzling because when I console.log word.value, I can see that the element is being accessed successfully. This indicates that the function is indeed changing the words as intended, yet the error persists. I find this discrepancy confusing and am unsure how to troubleshoot it effectively. It's worth noting that the error only surfaces in the VSC console, not in Google Chrome's console.

<span ref="word"></span>
onMounted(() => {
  randomizeText()
  wordChanger
})

onBeforeRouteLeave(() => {
  clearTimeout(wordChanger)
})

const wordChanger = setInterval(randomizeText, 4000)

const word = ref(null)
const words = reactive(['Word-1', 'Word-2'])
let i = 0

function randomizeText() {
  i = randomNum(i, words.length)
  const newWord = words[i]

  setTimeout(() => {
    word.value.textContent = newWord
  }, 200) // time to allow opacity to hit 0 before changing word
}

function randomNum(num, max) {
  let j = Math.floor(Math.random() * max)

  // ensure diff num every time
  if (num === j) {
    return randomNum(i, max)
  } else {
    return j
  }
}

Answer №1

Instead of utilizing const word = ref(null) as refs, you can directly reference it as the constant word within your template, and it will still function as expected.

<template>
  <div>
    <span>{{ word }}</span>
  </div>
</template>

When inside the setTimeout function, make sure to change word.value.textContent = newWord to word.value = newWord.

Here are the updated codes that have been tested and proven to work seamlessly.

<script setup lang="ts">
onMounted(() => {
  randomizeText()
  wordChanger
})

onBeforeRouteLeave(() => {
  clearTimeout(wordChanger)
})

const wordChanger = setInterval(randomizeText, 4000)

const word = ref('') // UPDATED
const words = reactive(['Word-1', 'Word-2'])
let i = 0

function randomizeText() {
  i = randomNum(i, words.length)
  const newWord = words[i]

  setTimeout(() => {
    word.value = newWord // UPDATED
  }, 200) // allowing opacity to reach 0 before changing word
}

function randomNum(num, max) {
  let j = Math.floor(Math.random() * max)

  // ensuring a different number each time
  if (num === j) {
    return randomNum(i, max)
  } else {
    return j
  }
}
</script>
<template>
  <div>
    <span>{{ word }}</span>
  </div>
</template>

I trust this explanation aids your understanding.

Answer №2

It seems like the issue here is related to timing, where the element may not be fully mounted while it is being manipulated by the code.

An alternative approach to directly setting the textContent property is to utilize the v-html directive and update the referenced variable (ref) instead. Additionally, you can initialize the interval within the onMounted() hook.

import {onMounted, reactive, ref} from "vue";
import {onBeforeRouteLeave} from "vue-router";

let wordChanger;

onMounted(() => {
    randomizeText()
    wordChanger = setInterval(randomizeText, 4000);
})

onBeforeRouteLeave(() => {
    clearTimeout(wordChanger)
})

let word = ref('Hello')
const words = reactive(['Word-1', 'Word-2'])
let i = 0

function randomizeText() {
    i = randomNum(i, words.length)
    const newWord = words[i]

    setTimeout(() => {
        word.value = newWord
    }, 200) // time to allow opacity to hit 0 before changing word
}

function randomNum(num, max) {
    let j = Math.floor(Math.random() * max)

    // ensure different number every time
    if (num === j) {
        return randomNum(i, max)
    } else {
        return j
    }
}
<span v-html="word"></span>

Answer №3

You may be misusing the ref 'word' and here are some other details I have highlighted:- note: I have added comments to the lines that I have modified for better clarity

setup() {
    

    const word = ref(null);
    const words = reactive(['Word-1', 'Word-2']);

    function randomizeText(i) {
      const p = randomNum(i, words.length);
      const newWord = words[p];

      setTimeout(() => {
        word.value = newWord;
      }, 200); // giving time for opacity to reach 0 before changing word
    }

    function randomNum(num, max) {
      let j = Math.floor(Math.random() * max);

      // ensuring different number every time
      if (num === j) {
        // note that I have used num instead of i here as well
        return randomNum(num, max);
      } else {
        return j;
      }
    }
    
    const wordChanger = setInterval(randomizeText, 4000);
    
    onMounted(() => {
      randomizeText(0); // starting with 0
      // wordChanger; // no need to use this here
    });

    onBeforeRouteLeave(() => {
      clearTimeout(wordChanger);
    });

    return {
      word,
    };
  },
<span>{{ word }}</span>

Check out a demo here:- https://stackblitz.com/edit/vue-rap7bb?file=src/components/HelloWorld.vue

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Sequencing time with Postgres, manipulating views with Angular

I am encountering issues with displaying graphs in AngularJS. My backend is written in nodeJS and includes an aggregator as a buffer for data received from netdata, which is then inserted into the database using a cron job. Now, with a new client request, ...

Transferring Variables from WordPress PHP to JavaScript

I have implemented two WordPress plugins - Snippets for PHP code insertion and Scripts n Styles for JavaScript. My objective is to automatically populate a form with the email address of a logged-in user. Here is the PHP snippet used in Snippets: <?p ...

Is it better to define a function within useEffect or externally?

What is the reason behind defining the fetchData function inside the useEffect instead of outside? Link: https://github.com/zeit/next.js/blob/canary/examples/with-graphql-faunadb/lib/useFetch.js import { useState, useEffect } from 'react' exp ...

Service in AngularJS designed specifically for storing and managing SEO metadata

I stumbled upon a tutorial that introduced me to using a service for dynamic SEO metadata here: However, I encountered an issue - It seems like the service is not accessible outside of the controller's view. <div ui-view></div> Here is t ...

"Although Vuex data is present, an error is being logged in the JavaScript console

I'm utilizing Vuex to retrieve data from a URL and I need to use this data in computed properties in Vue.js. What could be causing the issue? <script> import {mapGetters, mapActions} from "vuex"; computed: { ...mapGetters(["ON ...

Promise.all does not wait for the inner Promise.all to complete before continuing

let dataObj = [ { Id: 1, name: 'Alice', Address:[{ city: 'Paris', country: 'France' }] }, { Id: 2, name: 'Bob', Address: [{ city: 'NYC', country: &a ...

Tips for adjusting the vertical position of an image within a bootstrap column by a small amount

Apologies in advance if this question has already been addressed, and I am struggling to adapt it to my specific scenario. My objective is to adjust the positioning of the two images shown in the screenshot example below so that they align with the grey b ...

Is there a simple solution to show script 1 to visitors from the US and Canada, while displaying script 2 to visitors from other countries?

I'm looking for a simple script that can show one script to visitors from the US and Canada, and another script to visitors from other countries. It doesn't have to be perfect, but using a service like seems too complex for me. Is there a stra ...

I am confused about the process of mounting components

Utilizing pattern container/representational components, I have a CardContainer component that retrieves data from a server and passes it to a Card component. Container Component: class CardContainer extends Component { state = { 'ca ...

Does this information operate on Vue or Node?

I have recently started learning programming and currently working on an HTML project for school. My professor mentioned that we should only use Node.js for this project. However, I am concerned that the function I used below might be Vue instead of Node ...

Identifying and handling the removal of a complete div element by the user

Is it possible to remove the entire div element if a user tries to inspect the web browser using the script provided below? <script type="text/javascript"> eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/, ...

No files found in dist/ directory when using Vue.js

Beginner's Note I must confess that I am a novice when it comes to web development. Please bear with me if this question seems silly; I appreciate your assistance in advance. Initial Setup My current node version is 16.15.1 and npm version is 9.5.0 ...

JavaScript events for scrolling horizontally and vertically across multiple browsers

Is there a way to capture mousewheel and touchpad events, including on Mac, using JavaScript? Ideally, I want to get deltaX and deltaY values for both horizontal and vertical movements. I came across a website - - that appears to handle touchpad events ho ...

"Encountering a 'Cannot GET' error message while utilizing Rest API in Node.js

Currently, I am developing a project using nodejs along with the expressjs framework. My focus right now is on setting up and running a "Rest Api," but I seem to be encountering an error message that reads: Cannot GET /published Let me share my routes fil ...

I am looking to modify the background color of characters in a text box once the characters in a textarea exceed 150 characters

Currently, I am utilizing event.data to capture the text inputted into this particular HTML textbox. My intention is to change the background color to red based on that input. However, when using the style attribute on event.data, I encounter an error. It& ...

Tips for updating the content within an HTML tag with jQuery

I am looking to update the parameter value of an applet tag based on the selection from a dropdown menu. As I am new to jQuery, I would appreciate any guidance on how to achieve this using jQuery. This is my current applet code: <applet id="decisiontr ...

Observables waiting inside one another

I've encountered an issue where I need to return an observable and at times, within that observable, I require a value from another observable. To simplify my problem, let's consider the following code snippet: public dummyStream(): Observabl ...

Unlocking the Power of Global Props in AlpineJS: A Step-by-Step Guide

I'm currently exploring AlpineJS after having some experience with React and basic knowledge of Vue. One thing that has puzzled me about AlpineJS is how to update a state value from within a function, similar to how it's done in React. Let' ...

The module './installers/setupEvents' could not be located within Electron-Winstaller

After encountering an error while attempting to package my Angular app on Windows 10, I'm looking for help in resolving the issue: https://i.stack.imgur.com/yByZf.jpg The command I am using is: "package-win": "electron-packager . qlocktwo-app --ove ...

The access to the HTTP response object is not possible: the property is not found on the Object type

I recently created a response object and assigned it to the "this" object. However, when I try to access the datacentersinfo property, I encounter an error stating that the property does not exist on type Object. Due to this issue, I am unable to generat ...