如何通过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
相关产品推荐
相关产品推荐

