在Next.js中集成@mapbox/search-js-react遇document未定义错误
解决Next.js集成@mapbox/search-js-react时的
document is not defined错误 核心问题
@mapbox/search-js-web依赖浏览器环境的document对象,但你的页面使用getServerSideProps进行服务端渲染(SSR),服务端环境中不存在document,导致组件初始化时抛出错误。
解决方案
使用Next.js的dynamic导入功能,禁用该组件的服务端渲染,让它仅在客户端环境加载:
1. 修改组件导入方式
替换原来的静态导入为动态导入:
import dynamic from 'next/dynamic'; // 动态导入AddressAutofill,禁用SSR const AddressAutofill = dynamic( () => import('@mapbox/search-js-react').then((mod) => mod.AddressAutofill), { ssr: false } );
2. 修复signOut的副作用执行
原代码中直接在组件渲染阶段调用signOut()不符合React规范,会引发不必要的重渲染,改用useEffect处理副作用:
useEffect(() => { if (signOOut) { signOut(); } }, [signOOut]);
修改后的完整代码
import { getSession, signOut } from 'next-auth/react'; import { useState, useEffect } from 'react'; import dynamic from 'next/dynamic'; import Dashboard from '../../../components/layout/dashboard'; import { Container, Button, Table } from 'react-bootstrap'; // 动态导入AddressAutofill,禁用SSR const AddressAutofill = dynamic( () => import('@mapbox/search-js-react').then((mod) => mod.AddressAutofill), { ssr: false } ); export default function Details({ signOOut }) { useEffect(() => { if (signOOut) { signOut(); } }, [signOOut]); return ( <form> <AddressAutofill accessToken='pk.eyJw'> <input name='address' placeholder='Address' type='text' autoComplete='address-line1' /> </AddressAutofill> <input name='apartment' placeholder='Apartment number' type='text' autoComplete='address-line2' /> <input name='city' placeholder='City' type='text' autoComplete='address-level2' /> <input name='state' placeholder='State' type='text' autoComplete='address-level1' /> <input name='country' placeholder='Country' type='text' autoComplete='country' /> <input name='postcode' placeholder='Postcode' type='text' autoComplete='postal-code' /> </form> ); } export async function getServerSideProps(ctx) { const Gsession = await getSession(ctx); var signo = false; console.log('Checking Session are : ' + JSON.stringify(Gsession)); if (Gsession) { if (Gsession.error == 555) { signo = true; } } return { props: { sessions: Gsession, signOOut: signo, }, }; } Details.auth = true; Details.getLayout = function getLayout(page) { return <Dashboard>{page}</Dashboard>; };
补充说明
动态导入禁用SSR后,组件会在客户端hydrate完成后再加载,彻底避免了服务端访问document的问题。同时调整signOut的执行时机,符合React副作用处理的规范,避免渲染阶段的异常。
内容的提问来源于stack exchange,提问作者RUSSELL HARROWER
相关产品推荐
相关产品推荐

