NextJs中ReactPhotoSphereViewer组件引用无法获取,如何解决?
Next.js中ReactPhotoSphereViewer无法获取Ref的解决办法
问题场景
在Next.js里用react-photo-sphere-viewer展示全景图,基础功能没问题,但想通过ref调用组件的toggleAutorotate方法时,不管用createRef还是useRef都拿不到组件实例,而React项目里同样的代码完全正常。
问题根源
Next.js的dynamic导入会给组件套一层包装,直接传ref的话,绑到的是这个包装容器,不是真正的ReactPhotoSphereViewer实例,自然调用不了组件方法。
可行解决方案
方案1:用forwardRef包装动态导入的组件
把动态导入的组件用React.forwardRef包裹,让ref能穿透包装传递到原始组件:
import React, { useRef, useEffect } from "react"; import dynamic from 'next/dynamic' const ReactPhotoSphereViewer = dynamic( () => import('react-photo-sphere-viewer').then(mod => React.forwardRef((props, ref) => <mod.ReactPhotoSphereViewer {...props} ref={ref} /> ) ), { ssr: false } ) function PanoramaImage({ src }) { const photoSphereRef = useRef(null); useEffect(() => { if (photoSphereRef.current) { photoSphereRef.current.toggleAutorotate(); } }, []); return ( <div> <ReactPhotoSphereViewer ref={photoSphereRef} src={src} /> </div> ) } export default PanoramaImage;
方案2:页面级禁用SSR,直接导入组件
如果你的页面不需要服务端渲染,可以在页面文件顶部配置禁用SSR,这样就能像普通React项目一样直接导入组件,不用动态导入:
// Next.js 13+ App Router配置 export const config = { ssr: false }; // 或者Pages Router可通过getServerSideProps禁用(可选) // export async function getServerSideProps() { // return { props: {} } // } import { ReactPhotoSphereViewer } from 'react-photo-sphere-viewer'; import React, { useRef, useEffect } from 'react'; function PanoramaImage({ src }) { const photoSphereRef = useRef(null); useEffect(() => { photoSphereRef.current?.toggleAutorotate(); }, []); return ( <ReactPhotoSphereViewer ref={photoSphereRef} src={src} /> ); } export default PanoramaImage;
方案3:使用回调Ref
回调Ref不受动态导入包装的影响,直接把组件实例存到变量里:
import React, { useEffect } from "react"; import dynamic from 'next/dynamic' const ReactPhotoSphereViewer = dynamic( () => import('react-photo-sphere-viewer').then(mod => mod.ReactPhotoSphereViewer), { ssr: false } ) function PanoramaImage({ src }) { let photoSphereInstance = null; useEffect(() => { photoSphereInstance?.toggleAutorotate(); }, [photoSphereInstance]); return ( <div> <ReactPhotoSphereViewer ref={instance => photoSphereInstance = instance} src={src} /> </div> ) } export default PanoramaImage;
注意事项
- 别用
createRef(<ReactPhotoSphereViewer />)初始化ref,函数组件里优先用useRef(null),类组件用createRef()即可。 - useEffect的依赖数组里不用加ref,因为ref本身是稳定引用,current属性变化不会触发effect,直接留空或者跟踪回调里的实例变量就行。
内容的提问来源于stack exchange,提问作者Yusuf Arslan
相关产品推荐
相关产品推荐

