我正在尝试使用钩子在 React 中重新启动 GIF 动画
I am trying to restart a GIF animation in a React using hooks
我发现了类似的问题和我试图修改的答案我特别查看了 。这里的目标是让 GIF 在每次显示该组件时重新启动。我的示例代码已经过一两次迭代,现在就是这样。
import {useState, useEffect} from "react"
import Footer from "../components/Footer";
import NavMenu from '../components/NavMenu'
import {Box, Typography} from '@mui/material'
import backgroundImage from '../assets/images/world-bg.png'
import Logo from '../assets/images/chr-logo-white@2x.png'
import landscape from '../assets/gifs/why-we-exist_1test.gif'
import { Gif } from "@mui/icons-material";
const Exist = () => {
const [gif, setGif] =useState('')
const reloadGif = () => {
setGif('')
setTimeout(() => {
setGif(landscape)
}, 0)
}
useEffect(() => {
reloadGif()
return () => {
setGif('')
}
},[]
)
const styles ={
introContainer:{
height: '100%',
width: '100vw',
backgroundImage: `url(${backgroundImage})`,
display: 'flex',
flexDirection: 'column',
alignContent: 'center',
color:'white',
textAlign:'center',
justifyContent: 'center',
alignContent:'center',
flexShrink:0
}
}
return (
<Box sx = {styles.introContainer}>
<NavMenu />
<Box >
{gif !== '' && <img src={gif} alt="Logo"></img>}
</Box>
<Footer logo={false} back={'intro'} next={"home"}/>
</Box>
)
}
export default Exist;
我希望我的 useEffect 会清除图像 src,然后再次设置它以强制重新渲染。我看到的问题是,对于空的依赖数组,它不会触发重新渲染,但没有它,我会不断重新渲染,但 GIF 仍然只播放一次。
这里的问题很可能是您没有明确的方法来重新触发使用效果以使 Gif 重新加载。
对此有多种解决方案,但这取决于您如何实现显示和不显示组件的逻辑。
如您所知,只要将组件放在屏幕上,就会触发具有空依赖项数组的 useEffect。
作为解决方案,您需要检查当前如何将带有 gif 的组件渲染到屏幕上。你必须确保它是新添加到 DOM 的,只要你想播放 gif。
附带说明:您的 useEffect 中不需要 return 函数。
const ParentComponent = () => {
const [showChildComponent, setShowChildComponent] = useState(true)
return (
<>
<button onClick={() => {setShowChildComponent(!showChildComponent)}}>
Click me to show or hide the child component
</button>
{ showChildComponent && <ChildComponent /> }
</>
)
}
const ChildComponent = () => {
const [gif, setGif] =useState('')
const reloadGif = () => {
setGif('')
setTimeout(() => {
setGif(landscape)
}, 0)
}
useEffect(() => {
reloadGif()
},[]
)
return (<img src={gif} alt="Logo"></img>)
}
您还可以借助道具/状态重新触发 useEffect。
每次你的 showGif 状态改变时,下面的 useEffect 都会被重新触发,你可以在你想播放你的 gif 时设置它。
const [retriggerGif, setRetriggerGif] = useState(true)
useEffect(() => {
reloadGif()
},[retriggerGif]
)
如果您无法安装/卸载您的组件
在您提到的评论中,您使用基于散列的路由器并且只将您的组件包装在 RouterLink 中。
在这种情况下,您可以使 useEffect 取决于路由器的哈希值,并始终重新运行哈希值更改:
这当然取决于您使用的路由器,但总有办法获取当前活动路径并以某种方式散列。
在 react-router 中你例如可以像这样通过 useHistory()
钩子获取 history
对象:
const history = useHistory()
useEffect(() => {
// check that you are at the correct hash
if(history.hash === 'header') {
reloadGif()
}
}, [history])
以@Carolin 的回答为起点。我能够想出一个解决方案,但仍然感觉很笨拙,但它有效。
import {useEffect} from "react"
import Footer from "../components/Footer";
import NavMenu from '../components/NavMenu'
import {Box} from '@mui/material'
import backgroundImage from '../assets/images/world-bg.png'
import landscape from '../assets/gifs/why-we-exist_1test.gif'
const Exist = ({viewCount, handleView}) => {
useEffect(() => {
return () => {
return handleView(viewCount + 1)
}
},[])
const styles ={
introContainer:{
height: '100%',
width: '100vw',
backgroundImage: `url(${backgroundImage})`,
display: 'flex',
flexDirection: 'column',
alignContent: 'center',
color:'white',
textAlign:'center',
justifyContent: 'center',
alignContent:'center',
flexShrink:0
}
}
return (
<Box sx = {styles.introContainer}>
<NavMenu />
<Box >
{viewCount %2 === 0 && <img src={landscape + "?=" + Date.now()} alt="Logo"></img>}
{viewCount %2 !== 0 && <img src={landscape + "?=" + Date.now()} alt="Logo"></img>}
</Box>
<Footer logo={false} back={'intro'} next={"home"}/>
</Box>
)
}
export default Exist;
其中 viewCount 和 handleView 是来自父组件的 const [count, setCount]=useState(0)
props
我发现了类似的问题和我试图修改的答案我特别查看了
import {useState, useEffect} from "react"
import Footer from "../components/Footer";
import NavMenu from '../components/NavMenu'
import {Box, Typography} from '@mui/material'
import backgroundImage from '../assets/images/world-bg.png'
import Logo from '../assets/images/chr-logo-white@2x.png'
import landscape from '../assets/gifs/why-we-exist_1test.gif'
import { Gif } from "@mui/icons-material";
const Exist = () => {
const [gif, setGif] =useState('')
const reloadGif = () => {
setGif('')
setTimeout(() => {
setGif(landscape)
}, 0)
}
useEffect(() => {
reloadGif()
return () => {
setGif('')
}
},[]
)
const styles ={
introContainer:{
height: '100%',
width: '100vw',
backgroundImage: `url(${backgroundImage})`,
display: 'flex',
flexDirection: 'column',
alignContent: 'center',
color:'white',
textAlign:'center',
justifyContent: 'center',
alignContent:'center',
flexShrink:0
}
}
return (
<Box sx = {styles.introContainer}>
<NavMenu />
<Box >
{gif !== '' && <img src={gif} alt="Logo"></img>}
</Box>
<Footer logo={false} back={'intro'} next={"home"}/>
</Box>
)
}
export default Exist;
我希望我的 useEffect 会清除图像 src,然后再次设置它以强制重新渲染。我看到的问题是,对于空的依赖数组,它不会触发重新渲染,但没有它,我会不断重新渲染,但 GIF 仍然只播放一次。
这里的问题很可能是您没有明确的方法来重新触发使用效果以使 Gif 重新加载。
对此有多种解决方案,但这取决于您如何实现显示和不显示组件的逻辑。
如您所知,只要将组件放在屏幕上,就会触发具有空依赖项数组的 useEffect。
作为解决方案,您需要检查当前如何将带有 gif 的组件渲染到屏幕上。你必须确保它是新添加到 DOM 的,只要你想播放 gif。
附带说明:您的 useEffect 中不需要 return 函数。
const ParentComponent = () => {
const [showChildComponent, setShowChildComponent] = useState(true)
return (
<>
<button onClick={() => {setShowChildComponent(!showChildComponent)}}>
Click me to show or hide the child component
</button>
{ showChildComponent && <ChildComponent /> }
</>
)
}
const ChildComponent = () => {
const [gif, setGif] =useState('')
const reloadGif = () => {
setGif('')
setTimeout(() => {
setGif(landscape)
}, 0)
}
useEffect(() => {
reloadGif()
},[]
)
return (<img src={gif} alt="Logo"></img>)
}
您还可以借助道具/状态重新触发 useEffect。 每次你的 showGif 状态改变时,下面的 useEffect 都会被重新触发,你可以在你想播放你的 gif 时设置它。
const [retriggerGif, setRetriggerGif] = useState(true)
useEffect(() => {
reloadGif()
},[retriggerGif]
)
如果您无法安装/卸载您的组件
在您提到的评论中,您使用基于散列的路由器并且只将您的组件包装在 RouterLink 中。
在这种情况下,您可以使 useEffect 取决于路由器的哈希值,并始终重新运行哈希值更改:
这当然取决于您使用的路由器,但总有办法获取当前活动路径并以某种方式散列。
在 react-router 中你例如可以像这样通过 useHistory()
钩子获取 history
对象:
const history = useHistory()
useEffect(() => {
// check that you are at the correct hash
if(history.hash === 'header') {
reloadGif()
}
}, [history])
以@Carolin 的回答为起点。我能够想出一个解决方案,但仍然感觉很笨拙,但它有效。
import {useEffect} from "react"
import Footer from "../components/Footer";
import NavMenu from '../components/NavMenu'
import {Box} from '@mui/material'
import backgroundImage from '../assets/images/world-bg.png'
import landscape from '../assets/gifs/why-we-exist_1test.gif'
const Exist = ({viewCount, handleView}) => {
useEffect(() => {
return () => {
return handleView(viewCount + 1)
}
},[])
const styles ={
introContainer:{
height: '100%',
width: '100vw',
backgroundImage: `url(${backgroundImage})`,
display: 'flex',
flexDirection: 'column',
alignContent: 'center',
color:'white',
textAlign:'center',
justifyContent: 'center',
alignContent:'center',
flexShrink:0
}
}
return (
<Box sx = {styles.introContainer}>
<NavMenu />
<Box >
{viewCount %2 === 0 && <img src={landscape + "?=" + Date.now()} alt="Logo"></img>}
{viewCount %2 !== 0 && <img src={landscape + "?=" + Date.now()} alt="Logo"></img>}
</Box>
<Footer logo={false} back={'intro'} next={"home"}/>
</Box>
)
}
export default Exist;
其中 viewCount 和 handleView 是来自父组件的 const [count, setCount]=useState(0)
props