盖茨比的简单Javascript动画



我是React和Gatsby的新手,正在努力寻找将简单的Javascript动画应用于组件中DOM元素的最佳方法。我知道如何使用onClick等处理组件事件,但例如,我想每2秒连续更改Header.js组件中<span>的颜色。

import React from 'react';
export default function Header() {
return (
<header>
<p>This is a <span>test!</span></p>
</header>
)
}

然后我想使用一些JS,比如:

const spanEl = document.querySelector('header span');
let counter = 0;
const changeColor = () => {
if (counter % 2 == 0) {
spanEl.style.color = "red";
} else {
spanEl.style.color = "blue";
}
counter++;
if (counter == 10) counter = 0;
}
setInterval(changeColor, 2000);

我发现我可以在结束body标记之前将其放在html.js中的脚本标记中,但有没有办法将此功能保留在组件中?在这个框架内工作时,我是否需要完全重新思考我的方法?

如果你想用惯用的React来处理这个问题,那么我建议用钩子、组件生命周期和效果来表达这个行为。

官方的React挂钩和效果文档非常好,我会从那里开始。

import React from 'react';
const noop = () => null;
// Encapsulate the interval behavior
const useInterval = (callback, delay) => {
const savedCallback = useRef(noop);
useEffect(() => {
savedCallback.current = callback;
savedCallback.current();
}, [callback]);
useEffect(() => {
const id = setInterval(savedCallback.current, delay);
return () => clearInterval(id);
}, [delay]);
};
export default function Header() {
const [color, setColor] = useState("blue");
// setColor causes a re-render of the component
const updateColor = setColor(color === "blue" ? "red" : "blue");
useInterval(updateColor, 2000);
// Use the jsx to change the color instead of reaching into the dom
return (
<header>
<p>This is a <span style={{ color }}>test!</span></p>
</header>
)
}

[EDIT:我刚刚从@windowsill看到了答案,我认为它比我的好;我建议使用该解决方案。]

在React功能组件中,您需要使用useReference挂钩来针对元素(而不是使用document.querySelector()选择它(,并使用useEffecet挂钩来设置和清除组件装载/卸载时的超时:

import React, {
useEffect,
useRef,
useCallback
} from 'react';
export function Header() {
const animatedText = useRef(null);
const runAnimation = useCallback(elem => {
const currColour = elem.style.color;
elem.style.color = (currColour === 'red' && 'blue') || 'red';
}, []);
useEffect(() => {
const animationInterval = setInterval(() => {
runAnimation(animatedText.current);
}, 2000);
return () => {
clearInterval(animationInterval);
}
}, [runAnimation]);
return (
<header>
<p>This is a <span ref={animatedText}>test!</span></p>
</header>
);
}

useCallback钩子用于优化目的,并防止每次重新渲染组件时重新定义和初始化函数runAnimation

最新更新