Trying to use useRef to run a function on a generated item in React/Remix/Prisma

I’ve gone through multiple useRef/useEffect instructions but I just can’t seem to make it work here.

The code workflow here is: Remix/React, get data from database, display data, turn data into a ticker that can be updated

If anyone could point out any glaring errors they see in this code as to why the useEffect hook isn’t firing, or why the useRef hook can never find the {listRef} within the , I would love to know.

import { Links, redirect, useLoaderData, Outlet } from 'remix'
import { db } from '~/utils/db.server'
import { getUser } from '~/utils/session.server'
import { ReactSortable } from "react-sortablejs"
import { useState, useRef, useEffect } from 'react'
import tickerStylesUrl from '~/styles/tickerDisplay.css'

export const links = () => [{ rel: 'stylesheet', href: tickerStylesUrl }]

export const loader = async ({ request, params }) => {
  
  const user = await getUser(request)
  const ticker = await db.ticker.findUnique({
    where: { id: params.tickerId },
    include: {
      headlines: true,
    },
  })
  if (!ticker) throw new Error('Ticker not found')

  const data = { ticker, user }
  return data
}

export const action = async ({ request, params }) => {

}
// The ticker function displays the items without styling, so it finds the database perfectly and can get the data
function displayTicker() {
  const { ticker, user } = useLoaderData()

  const headlines = ticker.headlines
  const tickerParentStyle = {
    width: "1920px",
    height: "1080px",
    position: "relative",
    backgroundColor: "black"
  }
  const tickerStyle = {
    position: "absolute",
    padding: "0",
    bottom: "0",
    color: `${ticker.fontColor}`,
    backgroundColor: `${ticker.backgroundColor}`,
    fontFamily: `${ticker.font}`,
    fontSize: "2em",
  }
  const tickerHeadlineStyle = {
    margin: "auto",
    height: "50%",
  }

  // So begins the found ticker code I had hoped to integrate
  // Source: https://www.w3docs.com/tools/code-editor/2123
  function scrollTicker() {

    const marquee = listRef.current.querySelectorAll('.tickerHeadlines');
    let speed = 4;
    let lastScrollPos = 0;
    let timer;
    marquee.forEach(function (el) {
      const container = el.querySelector('.headlineItem');
      const content = el.querySelector('.headlineItem > *');
      //Get total width
      const elWidth = content.offsetWidth;
      //Duplicate content
      let clone = content.cloneNode(true);
      container.appendChild(clone);
      let progress = 1;
      function loop() {
        progress = progress - speed;
        if (progress <= elWidth * -1) {
          progress = 0;
        }
        container.style.transform = 'translateX(' + progress + 'px)';
        container.style.transform += 'skewX(' + speed * 0.4 + 'deg)';
        window.requestAnimationFrame(loop);
      }
      loop();
    });
    window.addEventListener('scroll', function () {
      const maxScrollValue = 12;
      const newScrollPos = window.scrollY;
      let scrollValue = newScrollPos - lastScrollPos;
      if (scrollValue > maxScrollValue) scrollValue = maxScrollValue;
      else if (scrollValue < -maxScrollValue) scrollValue = -maxScrollValue;
      speed = scrollValue;
      clearTimeout(timer);
      timer = setTimeout(handleSpeedClear, 10);
    });
    function handleSpeedClear() {
      speed = 4;
    }
  }

  const listRef = useRef()
  console.log("listRef: " + JSON.stringify(listRef))
  // This console appears everytime, but is always empty, presumably because DOM has just rendered

  useEffect(() => {
    console.log("useEffect fired")
    // This console NEVER fires, sadly. I thought this would happen ONCE rendered
  }, [listRef]);

  return (
    <>
      <Links />
      <div style={tickerParentStyle}>
        <div style={tickerStyle}>
          <div key={ticker.id} style={tickerHeadlineStyle} class="tickerWrapper">
            <ul className="tickerHeadlines" ref={listRef} style={{ margin: "10px 0 10px 0" }} >
              {/* Hoping to map through the ticker items here, and have them displayed in a list, which would then be manipulated by the useRef/useEffect hook */}
              {headlines.map((headline) => (
                <>
                  <li class="headlineItem" key={headline.id}>
                    <span>
                      {headline.content} {ticker.seperator}
                    </span>
                  </li>
                </>
              ))}
              {scrollTicker()}
            </ul>
          </div>
        </div>
      </div>
    </>
  )
}

export default displayTicker

As always, any help is appreciated.