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

Next.js中使用react-player的seekTo方法报错:seekTo is not a function

解决Next.js中ReactPlayer调用seekTo时报错"seekTo is not a function"的问题

问题根源

  1. 使用Next.js的dynamic导入ReactPlayer时,默认不会将ref转发到底层的ReactPlayer组件,导致playerRef.current无法获取到组件的真实实例,调用seekTo自然会报错。
  2. 代码中直接依赖外部player状态进行更新,存在状态不同步的潜在问题。

解决方案

1. 配置dynamic导入时转发ref

修改ReactPlayer的导入语句,添加forwardRef: true配置,让ref穿透到实际的ReactPlayer组件:

const ReactPlayer = dynamic(() => import("react-player"), { 
  ssr: false,
  forwardRef: true // 新增配置,开启ref转发
});

2. 正确调用seekTo方法

在handleSeekMouseUp中,通过playerRef.current访问组件实例,并添加空值检查避免意外报错:

const handleSeekMouseUp = (e) => {
  const seekValue = parseFloat(e.target.value);
  setPlayer(prev => ({ ...prev, seeking: false }));
  if (playerRef.current) {
    playerRef.current.seekTo(seekValue);
  }
};

3. 使用函数式更新避免状态不同步

所有状态更新操作改用函数式更新,确保获取到最新的state值:

const handlePlayPause = () => {
  setPlayer(prev => ({ ...prev, playing: !prev.playing }));
};

const handleMuted = () => {
  setPlayer(prev => ({ ...prev, muted: !prev.muted }));
};

const handleSeekMouseDown = () => {
  setPlayer(prev => ({ ...prev, seeking: true }));
};

const handleSeekChange = (e) => {
  setPlayer(prev => ({ ...prev, played: parseFloat(e.target.value) }));
};

完整修改后的代码

import { useRef, useState } from "react";
import dynamic from "next/dynamic";

const ReactPlayer = dynamic(() => import("react-player"), { 
  ssr: false,
  forwardRef: true
});

const Player = ({url}) => {
  const playerRef = useRef();

  const [player, setPlayer] = useState({
    playing: true,
    muted: true,
    played: 0,
    loaded: 0,
    duration: 0,
    seeking: false
  });

  const handlePlayPause = () => {
    setPlayer(prev => ({ ...prev, playing: !prev.playing }));
  };

  const handleMuted = () => {
    setPlayer(prev => ({ ...prev, muted: !prev.muted }));
  };

  const handleSeekMouseDown = () => {
    setPlayer(prev => ({ ...prev, seeking: true }));
  };

  const handleSeekChange = (e) => {
    setPlayer(prev => ({ ...prev, played: parseFloat(e.target.value) }));
  };

  const handleSeekMouseUp = (e) => {
    const seekValue = parseFloat(e.target.value);
    setPlayer(prev => ({ ...prev, seeking: false }));
    if (playerRef.current) {
      playerRef.current.seekTo(seekValue);
    }
  };

  const handleProgress = (state) => {
    if (!player.seeking) {
      setPlayer(state);
    }
  };

  return (
    <div className={`relative justify-center content-center w-full`}>
      <ReactPlayer
        ref={playerRef}
        className="absolute rounded"
        width="100%"
        height="100%"
        url={url}
        volume={1}
        playIcon={<></>}
        playing={player.playing}
        loop={true}
        muted={player.muted}
        onProgress={handleProgress}
      />

      <div
        className="absolute w-full h-full"
        onClick={handlePlayPause}
      />

      <div>
        <input
          type="range"
          min={0}
          max={0.999999}
          step="any"
          value={player.played}
          onMouseDown={handleSeekMouseDown}
          onChange={handleSeekChange}
          onMouseUp={handleSeekMouseUp}
        />
      </div>
    </div>
  );
};
 
export default Player;

内容的提问来源于stack exchange,提问作者MiMi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 02:30:50