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

如何通过react-full-screen从内部组件进入全屏模式

解决react-full-screen中父组件handle在子组件的调用问题

问题核心

你在InnerComponent中单独调用useFullScreenHandle()生成的handle,和FullScreenListener里的handle是完全独立的实例,而FullScreen组件只绑定了父组件的那个handle,所以子组件调用自己的handle不会触发全屏。

方案一:通过Context传递handle(推荐,适配多层组件嵌套)

1. 新建FullScreenContext文件

import React, { createContext, useContext } from 'react';
import { FullScreenHandle } from 'react-full-screen';

const FullScreenContext = createContext<FullScreenHandle | null>(null);

export const FullScreenProvider = FullScreenContext.Provider;

export const useFullScreen = () => {
  const context = useContext(FullScreenContext);
  if (!context) {
    throw new Error('useFullScreen必须在FullScreenProvider范围内使用');
  }
  return context;
};

2. 修改FullScreenListener组件

将handle通过Context提供给所有子组件:

import React from "react";
import { useFullScreenHandle, FullScreen } from "react-full-screen";
import { FullScreenProvider } from './FullScreenContext';

interface IProps {
  children: React.ReactNode;
}

const FullScreenListener = ({ children }: IProps) => {
  const handle = useFullScreenHandle();
  return (
    <FullScreenProvider value={handle}>
      <FullScreen handle={handle}>{children}</FullScreen>
    </FullScreenProvider>
  );
};

export default FullScreenListener;

3. 修改InnerComponent组件

通过自定义Hook获取Context中的handle:

import React from "react";
import { useFullScreen } from './FullScreenContext';

const InnerComponent = () => {
  const handle = useFullScreen();

  const handleClick = () => {
    console.log("click, go full screen!");
    handle.enter();
  };

  return (
    <>
      <button onClick={handleClick}>Go fullscreen</button>
    </>
  );
};

export default InnerComponent;

方案二:通过Render Props传递handle(适合浅层级组件嵌套)

修改FullScreenListener组件

import React from "react";
import { useFullScreenHandle, FullScreen } from "react-full-screen";

interface IProps {
  children: (handle: any) => React.ReactNode;
}

const FullScreenListener = ({ children }: IProps) => {
  const handle = useFullScreenHandle();
  return (
    <FullScreen handle={handle}>
      {children(handle)}
    </FullScreen>
  );
};

export default FullScreenListener;

修改App.tsx的调用方式

import FullScreenListener from "./FullScreenListener";
import InnerComponent from "./InnerComponent";

export default function App() {
  return (
    <div className="App">
      <FullScreenListener>
        {(handle) => <InnerComponent fullScreenHandle={handle} />}
      </FullScreenListener>
    </div>
  );
}

修改InnerComponent组件

import React from "react";
import { FullScreenHandle } from 'react-full-screen';

interface IProps {
  fullScreenHandle: FullScreenHandle;
}

const InnerComponent = ({ fullScreenHandle }: IProps) => {
  const handleClick = () => {
    console.log("click, go full screen!");
    fullScreenHandle.enter();
  };

  return (
    <>
      <button onClick={handleClick}>Go fullscreen</button>
    </>
  );
};

export default InnerComponent;

备选方案:原生浏览器全屏API实现(无需依赖第三方库)

封装FullScreen组件

import React, { useState, useEffect, useRef } from 'react';

interface FullScreenProps {
  children: React.ReactNode | ((props: {
    enterFullScreen: () => Promise<void>;
    exitFullScreen: () => Promise<void>;
    isFullScreen: boolean;
  }) => React.ReactNode);
}

const FullScreen = ({ children }: FullScreenProps) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const [isFullScreen, setIsFullScreen] = useState(false);

  useEffect(() => {
    const handleFullScreenChange = () => {
      setIsFullScreen(!!document.fullscreenElement);
    };

    document.addEventListener('fullscreenchange', handleFullScreenChange);
    return () => {
      document.removeEventListener('fullscreenchange', handleFullScreenChange);
    };
  }, []);

  const enterFullScreen = async () => {
    if (containerRef.current) {
      await containerRef.current.requestFullscreen();
    }
  };

  const exitFullScreen = async () => {
    await document.exitFullscreen();
  };

  return (
    <div ref={containerRef}>
      {typeof children === 'function' 
        ? children({ enterFullScreen, exitFullScreen, isFullScreen }) 
        : children}
    </div>
  );
};

export default FullScreen;

使用示例

// App.tsx
import FullScreen from "./FullScreen";
import InnerComponent from "./InnerComponent";

export default function App() {
  return (
    <div className="App">
      <FullScreen>
        {({ enterFullScreen }) => <InnerComponent onFullScreen={enterFullScreen} />}
      </FullScreen>
    </div>
  );
}

// InnerComponent.tsx
import React from "react";

interface IProps {
  onFullScreen: () => void;
}

const InnerComponent = ({ onFullScreen }: IProps) => {
  return (
    <>
      <button onClick={onFullScreen}>Go fullscreen</button>
    </>
  );
};

export default InnerComponent;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:27:45