英文:
Force GIF image reload in React
问题
我需要重新加载一个GIF图像(CHECKMARK_ANIMATION_ICON
是源),以便每12秒或每当activeIndex
更改时开始GIF动画。
这是我的代码:
const reloadImgSource = (imgSource) => {
setTimeout(() => {
setImgSource("");
setImgSource(imgSource);
}, 1);
};
const handleActiveDot = (index, item) => {
setActiveIndex(index);
setActiveTopBonus(item);
reloadImgSource(CHECKMARK_ANIMATION_ICON);
};
useEffect(() => {
const activeIndexInterval = setInterval(() => {
reloadImgSource(CHECKMARK_ANIMATION_ICON);
if (topBonusList && activeIndex !== topBonusList.length - 1) {
setActiveIndex(activeIndex + 1);
} else {
setActiveIndex(0);
}
}, 12000);
return () => clearInterval(activeIndexInterval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeIndex, topBonusList]);
<img src={`${imgSource}`} alt="Checkmark Icon" />
这段代码是有效的,但我认为reloadImgSource
中的解决方案是一种变通方法。
我将setTimeout设置为1
,因为否则动画不会触发,因为源未设置为空字符串,然后再设置回原始值以重新触发GIF。
是否有更好的解决方案可以用于reloadImgSource
,允许我在函数触发时触发GIF的加载?
请注意,我不能在图像源中使用哈希,因为GIF不会被缓存,这对我来说是个问题。
英文:
I need to reload a GIF image (CHECKMARK_ANIMATION_ICON
is the source) to start the gif animation every 12 seconds or every time the activeIndex
is changing.
This is my code:
const reloadImgSource = (imgSource) => {
setTimeout(() => {
setImgSource("");
setImgSource(imgSource);
}, 1);
};
const handleActiveDot = (index, item) => {
setActiveIndex(index);
setActiveTopBonus(item);
reloadImgSource(CHECKMARK_ANIMATION_ICON);
};
useEffect(() => {
const activeIndexInterval = setInterval(() => {
reloadImgSource(CHECKMARK_ANIMATION_ICON);
if (topBonusList && activeIndex !== topBonusList.length - 1) {
setActiveIndex(activeIndex + 1);
} else {
setActiveIndex(0);
}
}, 12000);
return () => clearInterval(activeIndexInterval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeIndex, topBonusList]);
<img src={`${imgSource}`} alt="Checkmark Icon" />
This code is working but I think the solution in reloadImgSource
is a workaround.
I used setTimeout set to 1
because otherwise the animation is not triggered as the source is not set to an empty string and then back to the original value to retrigger the GIF.
Is there a better solution I can implement for reloadImgSource
that allows me to trigger the load of the GIF when the function is fired?
Note that I cannot use hash in the image source as the gif will not be cached and this is a problem for me
答案1
得分: 0
有一种方法可以做到这一点:
function App() {
const [activeInbox, setActiveInbox] = useState(0);
const [animation, setAnimation] = useState(false);
useEffect(() => {
setAnimation(true);
const timeout = setTimeout(() => {
setAnimation(false);
}, 1200);
return () => {
clearTimeout(timeout);
};
}, [activeInbox]);
return (
<div className="App">
{animation && (
<img
src={`https://cdn.dribbble.com/users/315048/screenshots/3710002/check.gif?${activeInbox}`}
/>
)}
<button onClick={() => setActiveInbox((i) => i + 1)}>
Change active inbox
</button>
</div>
);
}
但我建议避免这种实现方式,因为GIF文件可能无法正确缓存,客户端将在每次更新收件箱时加载新的GIF。如果可以使用其他类型的动画,请考虑使用SVG。
英文:
There is a way how you can do that
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function App() {
const [activeInbox, setActiveInbox] = useState(0);
const [animation, setAnimation] = useState(false);
useEffect(() => {
setAnimation(true);
const timeout = setTimeout(() => {
setAnimation(false);
}, 1200);
return () => {
clearTimeout(timeout);
};
}, [activeInbox]);
return (
<div className="App">
{animation && (
<img
src={`https://cdn.dribbble.com/users/315048/screenshots/3710002/check.gif?${activeInbox}`}
/>
)}
<button onClick={() => setActiveInbox((i) => i + 1)}>
Change active inbox
</button>
</div>
);
}
<!-- end snippet -->
But I'd suggest avoiding such kind of implementations because the gif won't be cached properly, and the client will load a new gif every inbox update. If you can use another kind of animation, look at SVG.
答案2
得分: 0
useState钩子不会逐行立即更改状态,而是安排更新状态,这是第一个尝试清空imgSource的setImgSource将被忽略的原因。
尝试:
const reloadImgSource = (imgSource) => {
setImgSource("");
setTimeout(() => {
setImgSource(imgSource);
}, 1);
};
英文:
useState hook doesn't change state immediately line by line, but it schedule updating state, it is the reason the first setImgSource which tries to empty imgSource will be ignored.
try:
const reloadImgSource = (imgSource) => {
setImgSource("");
setTimeout(() => {
setImgSource(imgSource);
}, 1);
};
答案3
得分: 0
以下是翻译好的代码部分:
const [imgSource, setImgSource] = useState(ANIMATION_ICON);
const reloadImgSource = async (imgSource) => {
setImgSource(imgSource);
};
const animationTrigger = async () => {
await reloadImgSource("");
await reloadImgSource(ANIMATION_ICON);
};
const handleActiveDot = (index, item) => {
setActiveIndex(index);
setActiveTopBonus(item);
animationTrigger();
};
useEffect(() => {
const activeIndexInterval = setInterval(() => {
animationTrigger();
if (topBonusList && activeIndex !== topBonusList.length - 1) {
setActiveIndex(activeIndex + 1);
} else {
setActiveIndex(0);
}
}, 12000);
return () => clearInterval(activeIndexInterval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeIndex, topBonusList]);
<img src={imgSource} alt="Animation Icon" />
英文:
For anyone interested, I arrived at this better solution to remove the workaround with setTimeout
, the result is the same but the code is more clean and readable, and avoids all caching issues:
const [imgSource, setImgSource] = useState(ANIMATION_ICON);
const reloadImgSource = async (imgSource) => {
setImgSource(imgSource);
};
const animationTrigger = async () => {
await reloadImgSource("");
await reloadImgSource(ANIMATION_ICON);
};
const handleActiveDot = (index, item) => {
setActiveIndex(index);
setActiveTopBonus(item);
animationTrigger();
};
useEffect(() => {
const activeIndexInterval = setInterval(() => {
animationTrigger();
if (topBonusList && activeIndex !== topBonusList.length - 1) {
setActiveIndex(activeIndex + 1);
} else {
setActiveIndex(0);
}
}, 12000);
return () => clearInterval(activeIndexInterval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeIndex, topBonusList]);
<img src={imgSource} alt="Animation Icon" />
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论