NextRouter未挂载错误求助:租房应用搜索页问题排查
问题原因
这个错误的核心原因是:你在服务器端渲染阶段调用了useRouter,而Next.js的Router实例仅在客户端浏览器环境中才会被挂载,服务器端不存在Router对象,因此触发了NextRouter was not mounted错误。你的Search页面属于pages目录下的页面,默认会执行服务器端渲染(SSR)或静态生成,组件初始化时在服务器端执行到const router = useRouter()就会报错。
解决方案
方案1:移除未使用的useRouter
从你的代码来看,目前并没有实际用到router对象,只是引入并声明了它。直接删除相关代码即可快速解决问题:
修改后的search.tsx:
import { useState } from 'react'; import Image from 'next/image'; import { Flex, Box, Text, Icon } from '@chakra-ui/react'; import { BsFilter } from 'react-icons/bs'; import SearchFilters from '../components/SearchFilters'; const Search = () => { const [searchFilters, setSearchFilters] = useState(false); return ( <Box> <Flex cursor="pointer" bg="gray.100" borderBottom="1px" borderColor="gray.200" p="2" fontWeight="black" fontSize="lg" justifyContent="center" alignItems="center" onClick={() => setSearchFilters((prevFilters) => !prevFilters)} > <Text>Filtrele</Text> <Icon paddingLeft="2" w="7" as={BsFilter}></Icon> </Flex> {searchFilters && <SearchFilters />} </Box> ) } export default Search;
方案2:若需使用router,确保仅在客户端执行
如果之后需要用到router功能,可以通过以下方式保证useRouter只在客户端环境运行:
方法A:用useEffect延迟获取router
利用React的useEffect仅在客户端执行的特性,将router的初始化逻辑放入effect中:
import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import Image from 'next/image'; import { Flex, Box, Text, Icon } from '@chakra-ui/react'; import { BsFilter } from 'react-icons/bs'; import SearchFilters from '../components/SearchFilters'; const Search = () => { const [searchFilters, setSearchFilters] = useState(false); const [router, setRouter] = useState(null); useEffect(() => { // 此代码块仅在客户端执行 const routerInstance = useRouter(); setRouter(routerInstance); }, []); // 使用router前先判断是否存在 const handleNavigation = () => { if (router) { // 示例:router.push('/results') } } return ( <Box> <Flex cursor="pointer" bg="gray.100" borderBottom="1px" borderColor="gray.200" p="2" fontWeight="black" fontSize="lg" justifyContent="center" alignItems="center" onClick={() => setSearchFilters((prevFilters) => !prevFilters)} > <Text>Filtrele</Text> <Icon paddingLeft="2" w="7" as={BsFilter}></Icon> </Flex> {searchFilters && <SearchFilters />} </Box> ) } export default Search;
方法B:标记为客户端组件(Next.js 13+)
如果你使用的是Next.js 13及以上版本,直接在组件顶部添加'use client'指令,强制组件仅在客户端渲染:
'use client'; import { useState } from 'react'; import { useRouter } from 'next/router'; import Image from 'next/image'; import { Flex, Box, Text, Icon } from '@chakra-ui/react'; import { BsFilter } from 'react-icons/bs'; import SearchFilters from '../components/SearchFilters'; const Search = () => { const [searchFilters, setSearchFilters] = useState(false); const router = useRouter(); return ( <Box> <Flex cursor="pointer" bg="gray.100" borderBottom="1px" borderColor="gray.200" p="2" fontWeight="black" fontSize="lg" justifyContent="center" alignItems="center" onClick={() => setSearchFilters((prevFilters) => !prevFilters)} > <Text>Filtrele</Text> <Icon paddingLeft="2" w="7" as={BsFilter}></Icon> </Flex> {searchFilters && <SearchFilters />} </Box> ) } export default Search;
方法C:用dynamic导入禁用SSR(Next.js 12及更早)
创建单独的客户端组件SearchClient.tsx:
// SearchClient.tsx import { useState } from 'react'; import { useRouter } from 'next/router'; import Image from 'next/image'; import { Flex, Box, Text, Icon } from '@chakra-ui/react'; import { BsFilter } from 'react-icons/bs'; import SearchFilters from '../components/SearchFilters'; const SearchClient = () => { const [searchFilters, setSearchFilters] = useState(false); const router = useRouter(); return ( <Box> <Flex cursor="pointer" bg="gray.100" borderBottom="1px" borderColor="gray.200" p="2" fontWeight="black" fontSize="lg" justifyContent="center" alignItems="center" onClick={() => setSearchFilters((prevFilters) => !prevFilters)} > <Text>Filtrele</Text> <Icon paddingLeft="2" w="7" as={BsFilter}></Icon> </Flex> {searchFilters && <SearchFilters />} </Box> ) } export default SearchClient;
修改原search.tsx,用dynamic导入并禁用SSR:
// search.tsx import dynamic from 'next/dynamic'; const SearchClient = dynamic(() => import('./SearchClient'), { ssr: false }); const Search = () => { return <SearchClient />; } export default Search;
内容的提问来源于stack exchange,提问作者gotdazaza
相关产品推荐
相关产品推荐

