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

React中无法在map内使用useState时,如何传递当前激活视频URL至VideoModal组件?

解决在React Map函数外传递激活视频URL至模态框的问题

嘿,我明白你的困扰了——React确实不允许在map这类循环回调里使用useState Hook,因为Hook的调用必须遵循React的规则(只能在组件顶层或者自定义Hook里调用)。不过没关系,我们可以通过状态提升的方式轻松解决这个问题,把当前激活视频的URL存在组件顶层的状态里,再传递给VideoModal就好啦!

具体解决方案步骤:

  1. 在Videos组件顶层添加状态变量,用来存储当前要在模态框中播放的视频URL:

    import { useState, useEffect } from 'react';
    
    // 你的Videos组件内部
    const [activeVideoUrl, setActiveVideoUrl] = useState('');
    // 假设你已经有isModalOpen和closeModal的状态/函数
    
  2. 同步当前激活视频的URL:
    如果你是通过currentItem来标记激活视频的,可以用useEffect监听currentItem的变化,自动更新对应的视频URL:

    useEffect(() => {
      // 从视频列表中找到当前激活项的URL
      const targetVideo = VIDEO_LIST.find(video => video.id === currentItem);
      if (targetVideo) {
        setActiveVideoUrl(targetVideo.url);
      }
    }, [currentItem]);
    

    或者,如果你是通过点击某个视频来打开模态框的,也可以直接在点击事件里设置URL:

    // 在map循环的每个视频项上添加点击事件
    <div key={props.id} onClick={() => {
      setActiveVideoUrl(props.url);
      setIsModalOpen(true); // 直接打开模态框
    }}>
      {/* 视频内容 */}
    </div>
    
  3. 把状态传递给VideoModal:
    现在只需要把activeVideoUrl作为videoURL属性传给模态框就可以了:

    <div className="play__video">
      {isModalOpen && (
        <VideoModal handleCloseModal={closeModal} videoURL={activeVideoUrl} />
      )}
    </div>
    

修改后的完整Videos.tsx示例:

import { useState, useEffect } from 'react';
import ReactPlayer from 'react-player';
import VideoModal from './VideoModal';

const Videos = () => {
  const [currentItem, setCurrentItem] = useState(/* 你的初始值 */);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [activeVideoUrl, setActiveVideoUrl] = useState('');

  // 同步当前激活视频的URL
  useEffect(() => {
    const targetVideo = VIDEO_LIST.find(video => video.id === currentItem);
    if (targetVideo) {
      setActiveVideoUrl(targetVideo.url);
    }
  }, [currentItem]);

  const closeModal = () => {
    setIsModalOpen(false);
  };

  const openModal = () => {
    setIsModalOpen(true);
  };

  return (
    <>
      <div className="video__container">
        <div className="video__item">
          {VIDEO_LIST.map((video: any) => (
            <div key={video.id}>
              {video.id === currentItem && (
                <>
                  <ReactPlayer 
                    url={video.url} 
                    playing={true} 
                    loop={true} 
                    volume={0} 
                    muted={true} 
                    height="100%" 
                    width="100%" 
                    controls={true} 
                    config={{ 
                      file: { 
                        attributes: { 
                          disablepictureinpicture: "true", 
                          controlsList: "disablepictureinpicture nodownload noplaybackrate", 
                        }, 
                      }, 
                    }} 
                  />
                  {/* 添加打开模态框的按钮 */}
                  <button onClick={openModal}>在模态框中播放</button>
                </>
              )}
            </div>
          ))}
        </div>
      </div>
      <div className="play__video">
        {isModalOpen && (
          <VideoModal handleCloseModal={closeModal} videoURL={activeVideoUrl} />
        )}
      </div>
    </>
  );
};

export default Videos;

原理说明:

核心思路就是把状态提升到组件的顶层作用域,避免在循环回调里使用Hook。通过useEffect监听激活项的变化,或者直接通过点击事件设置目标URL,就能让模态框始终拿到当前需要播放的视频地址啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 23:07:41