我已经看过多个useRef/useEffect指令,但我似乎无法在这里工作。
这里的代码工作流程是:混合/反应,从数据库获取数据,显示数据,将数据转换为可以更新的代码。
如果有人能指出他们在这段代码中看到的任何明显错误,说明为什么useEffect钩子没有启动,或者为什么useRef钩子永远找不到<ul>中的{listRef},我很想知道。
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%",
}
console.log("Headlines: " + headlines)
// 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">
// HERE IS THE TARGET UL
<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一如既往,任何帮助都是值得感激的。
发布于 2022-01-29 19:11:13
useRef是一个用于访问DOM元素的钩子,直接在React应用程序中操作DOM破坏了声明式编程的全部要点。不建议直接使用任何DOM对象和方法(如document )来操作dom。进入useEffect钩子时,useEffect钩子将根据依赖数组中提供的内容有条件地运行,如果没有,则该钩子在组件完成挂载后只运行一次。因此,您应该注意需要传递给useEffect依赖数组的内容。考虑到您的情况,当您传递listRef时,useEffect只在对象中发生更改而不是它的属性发生更改时才运行,因为对象是非原始的,因此该属性中的任何更改都不会被视为对象中的更改,而它仅仅是一个不会导致重呈现的对象属性突变。为了避免这种情况,您应该确信,正如您前面提到的,您希望在数据呈现后立即运行它,您可以在依赖项数组中使用headlines。将依赖项数组更改为包含headlines。
useEffect(() => {
console.log("useEffect fired")
// This console NEVER fires, sadly. I thought this would happen ONCE rendered
}, [headlines]);或者,您也可以将其保留为空,使其在组件挂载后只运行一次。
useEffect(() => {
console.log("useEffect fired")
// This console NEVER fires, sadly. I thought this would happen ONCE rendered
}, []);请注意,每次headlines发生更改时,前者都会运行一次,而后者无论发生什么变化都只运行一次。因此,根据您的用例,您可能希望选择最适合您的需求。
发布于 2022-02-02 20:44:30
有几件事情可以让代码变得更好:
启动ref
中调用“scrollTicker”函数
当组件退出时,
useEffect(() ) => { //在这里使用你的参考资料。返回() => { //删除链接器
};};
https://stackoverflow.com/questions/70878916
复制相似问题