You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Video组件点击后控制台打印play为false的生命周期疑问

问题根因

你的现象由React state异步更新特性、useEffect清理函数逻辑错误、缺少播放结束监听三个问题共同导致:

  • React的state更新是异步批量处理的,调用setPlay(true)后,当前作用域内的play变量仍然是本次渲染的旧值,需要等组件完成重渲染后才会拿到更新后的state。你在点击回调内和setPlay同作用域打印play,拿到的永远是点击前的状态,所以输出false。
  • useEffect的清理函数会在每次依赖项变化、下一轮effect执行前触发,你在清理函数中写了setPlay(false),相当于你刚把play改为true触发effect前,状态就被清理函数重置为false,逻辑完全错误。
  • 你没有绑定video的ended事件,视频播放结束后不会触发状态变更,永远不会打印预期的结束状态false。

修正后代码

const Video = ({src, type, index, isAutoPlay}) => {
  
  const [play, setPlay] = useState(isAutoPlay)
  const playRef = useRef();

  // 状态变更后再执行播放/暂停逻辑和打印
  useEffect(() => {
    if (!playRef.current) return
    if (play) {
      playRef.current.play();
      console.log(true)
    } else {
      playRef.current.pause();
      console.log(false)
    }
  }, [play]);

  // 监听播放结束事件修改状态
  const handleEnded = () => setPlay(false)

  return (
    <>
      <video 
       className="slide" 
       ref={playRef} 
       onClick={() => setPlay(true)}
       onEnded={handleEnded}>
        <source src={src} type={type} key={index}/>
        Your browser does not support the video tag.
      </video>
    </>
  )
}

修正说明

  1. 将状态打印逻辑移到useEffect中,保证只有state真的更新完成后才打印,拿到的永远是最新值
  2. 删除了useEffect中错误的清理函数,避免状态被意外重置
  3. 新增onEnded事件监听,视频播放完成后自动更新状态触发false打印
  4. 补充了暂停逻辑,后续如果需要实现点击切换播放/暂停,直接将点击回调改为setPlay(prev => !prev)即可

内容的提问来源于stack exchange,提问作者Amâncio de Noronha Brito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 07:48:00