I am trying to implement useEffect
on my React project to add my external JS file in.
This is my React code currently, with the mented out list being what I am trying to access from my script:
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import './HeroSec.css';
import '../script.js';
function HeroSec(){
useEffect(() => {
console.log('render');
const script = document.createElement('script');
script.src = "../script.js";
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
}
})
return(
<div className='hero-container'>
<h1>Example Name </h1>
{/*
<ul id="foo" class="hidden-text">
<li> E </li>
<li class="hidden">x</li>
<li class="hidden">a</li>
<li class="hidden">m</li>
<li class="hidden">p</li>
<li class="hidden">l</li>
<li class="hidden">e</li>
<li class="spaced">N</li>
<li class="hidden">a</li>
<li class="hidden">m</li>
<li class="hidden">e</li>
</ul>
*/}
and this is the script.js file I am getting the error in.
const text = document.querySelector("#foo");
setTimeout(() => {
text.classList.toggle("hidden-text");
}, 1000);
Essentially, I am just trying to grab that list element in React, and use the script to set a timeout so I can toggle off the hidden-text class. Of course there is some CSS that does this separately.
Hopefully I made it easy to understand the bigger picture of what I am trying to do and any help on that would be appreciated. In terms of the specific TypeError
I am getting, is there maybe another property instead of classList that I can use to access the list from within React?
I am trying to implement useEffect
on my React project to add my external JS file in.
This is my React code currently, with the mented out list being what I am trying to access from my script:
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import './HeroSec.css';
import '../script.js';
function HeroSec(){
useEffect(() => {
console.log('render');
const script = document.createElement('script');
script.src = "../script.js";
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
}
})
return(
<div className='hero-container'>
<h1>Example Name </h1>
{/*
<ul id="foo" class="hidden-text">
<li> E </li>
<li class="hidden">x</li>
<li class="hidden">a</li>
<li class="hidden">m</li>
<li class="hidden">p</li>
<li class="hidden">l</li>
<li class="hidden">e</li>
<li class="spaced">N</li>
<li class="hidden">a</li>
<li class="hidden">m</li>
<li class="hidden">e</li>
</ul>
*/}
and this is the script.js file I am getting the error in.
const text = document.querySelector("#foo");
setTimeout(() => {
text.classList.toggle("hidden-text");
}, 1000);
Essentially, I am just trying to grab that list element in React, and use the script to set a timeout so I can toggle off the hidden-text class. Of course there is some CSS that does this separately.
Hopefully I made it easy to understand the bigger picture of what I am trying to do and any help on that would be appreciated. In terms of the specific TypeError
I am getting, is there maybe another property instead of classList that I can use to access the list from within React?
- Are the ment markers around your element with id "foo" really there? – ASDFGerte Commented Mar 12, 2021 at 19:23
- Yes. Idk why stackoverflow shows them unmented. But yes, on my end they are mented simply because I wanted to ment them out until I figured out the problem here. – dom-nooch Commented Mar 12, 2021 at 19:27
- So you mented out the element with id "foo", then search for your element with id "foo", don't find it, and then be confused? – ASDFGerte Commented Mar 12, 2021 at 19:28
- LOL, no sir. The error I was getting was without the mented element "foo". Like I said, I just put the ments there now until I figured out what was wrong. I cannot tell if you are trying to be helpful or rude? – dom-nooch Commented Mar 12, 2021 at 19:31
-
That's fine then, i've just seen some things on this site, so i better make sure. You seem to
import '../script.js';
as well, but also inject it into DOM as a script element, why the doubling? Theimport
part is probably done immediately, soconst text = document.querySelector("#foo");
in there would execute before react had any time to render. – ASDFGerte Commented Mar 12, 2021 at 19:37
2 Answers
Reset to default 3Ideally you use the useRef
hook to access element with React function ponents. For example:
export default function HeroSec() {
const listElement = useRef(null);
useEffect(() => {
setTimeout(() => {
listElement.current.classList.add("hidden-text");
}, 1000);
return () => {};
});
return (
<div className="hero-container">
<h1>Example Name </h1>
<ul ref={listElement} id="foo">
<li> E </li>
<li className="hidden">x</li>
<li className="hidden">a</li>
</ul>
</div>
);
}
Sandbox: https://codesandbox.io/s/frosty-cache-6rkdq?file=/src/App.js
This is not the "react" way of doing things, you should not be getting direct references to html elements and modifying them in React. I did not quite understand what you want to do but you can try below approach to render ponents differently according to the state.
function HeroSec(){
const [toggled,setToggled] = useState(false);
...
return ( ....
//Component will have different class based on the value of toggled and
// when toggled value changed react will re-render the element with new value
<ul id="foo" class={toggled ? : "hidden-text" : <another_classname>} >
...)
Then use setToggled in your setTimeout function to change toggled from false to true.