I have a function that is supposed to change words every few seconds. Everything works as expected, but I get following error every few seconds 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)
I don’t understand why I get this error, because when I console.log word.value
, I get the element. So I have access to it and the function is working, the words change every few seconds, as expected. I’m a bit confused and don’t know how to get the problem solved. I don’t get the error in the Google Chrome console, only in VSC.
<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
}
}
3
Answers
Instead of using the
const word = ref(null)
asrefs
. You can directly call it the constantword
in your template. It should still work the same.Inside the
setTimeout
function, change thisword.value.textContent = newWord
to thisword.value = newWord
.Here is the updated codes. Tested and it works.
Hope that helps you.
This is probably a timing issue (element not mounted while it is being changed by the code)
You can do this without setting the textContent property dirctly, by using the
v-html
directive and just changing the referenced variable (ref)Also, you can just start the interval in the
onMounted()
hook.You probably are using the ref ‘word’ wrong and some other details I share below:-
note: I add comments to the lines I changed to help you understand better
here’s a demo:- https://stackblitz.com/edit/vue-rap7bb?file=src/components/HelloWorld.vue