Hi I'm new here and I was trying to learn react js along with intersection observer api,
I was trying to get all elements with .cards class using .querySelectorAll(".cards");
,
my problem is that it was returning an empty nodelist instead of a list of my elements.
I thought its on the initializing of the elements on my components so I tried putting defer attribute on my script and put it below the root elemen but it didnt work either.
HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title> Intersection Obsever </title>
</head>
<body>
<div id="root"></div>
<script defer type="module" src="/src/main.jsx"></script>
<script defer src="/src/Intersection Observer/intersection-observer.js"></script>
<script defer src="/src/Intersection Observer/Observer.js"></script>
</body>
</html>
App Component
import CardHolder from './Components/CardHolder'
import './App.css'
function App() {
return (
<>
<CardHolder/>
</>
)
}
export default App
CardHolder Component
import Cards from "./Cards";
function CardHolder() {
return (
<div className="cardHolder">
<h1 style={{color: "lightblue"}}> Cards </h1>
<Cards/>
</div>
)
}
export default CardHolder;
Cards Component
function Cards() {
return (
<>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
</>
)
}
export default Cards;
Observer js
const observer = new IntersectionObserver(entries => {
entries.forEach(en => {
if (en.isIntersecting) {
en.target.classList.add("show");
} else { en.target.classList.remove("show");}
})
}, {
threshold: 0.5
})
const cards = document.querySelectorAll(".cards");
cards.forEach(card => {
observer.observe(card);
})
I was trying get the cards elements and put it into the card variable so I can observe every each of them using forEach
One example would be to use a hook.
// useCardObserver.js
const makeObserver = () => {
return new IntersectionObserver(entries => {
entries.forEach(en => {
if (en.isIntersecting) {
en.target.classList.add("show");
} else { en.target.classList.remove("show");}
})
}, {
threshold: 0.5
})
}
const useCardObserver = (divRef) => {
const [observer, setObserver] = useState(makeObserver())
useEffect(() => {
if (divRef.current) {
const cards = divRef.current.querySelectorAll(".cards");
cards.forEach(card => {
observer.observe(card);
})
}
return () => {
if (divRef.current) {
const cards = divRef.current.querySelectorAll(".cards");
cards.forEach(card => {
observer.unobserve(card);
})
}
}
}, [divRef.current])
return null
}
And call it inside your Cards component using a ref as argument.
function Cards() {
const ref = useRef()
useCardObserver(ref)
return (
<div ref={ref}>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
<div className="cards"> Cards </div>
</div>
)
}
export default Cards;