NextJS 13 - 客户端组件内未定义窗口和本地存储

问题描述 投票:0回答:1

我正在使用 NextJS 13 及其应用程序路由器编写一个简单的 React CRUD 应用程序。

我有一条路线,其中

page.tsx
是客户端组件。

page.tsx

'use client'

import DataGrid from './DataGrid'

const List = (props) => (
   <DataGrid>...</DataGrid>
)

export default List

DataGrid.tsx

'use client'
const DataGrid = ({entity, identifier}) => {
   const gridIdentifier = `${window.location.pathname}-${entity}`;
   const gridSettings = JSON.parse(localStorage.getItem(gridIdentifier) || '{}');
   
   return ...
}

export default DataGrid

当我尝试按路线行驶时,控制台会显示

 ✓ Compiled in 1638ms (12671 modules)
 X src/common/components/DataGrid/DataGrid.tsx (55:26) @ DataGrid
 X ReferenceError: window is not defined
    at DataGrid (./src/common/components/DataGrid/DataGrid.tsx:40:28)
  53 |   const router = useRouter();
  54 |   const ModalFormComponent = modalFormComponent as React.ElementType;
> 55 |   const gridIdentifier = `${window.location.pathname}-${entity}`;
     |                          ^
  56 |   const gridSettings = JSON.parse(localStorage.getItem(gridIdentifier) || '{}');
  57 |   
 ✓ Compiled /not-found in 758ms (12676 modules)

use client
指令不是应该允许使用浏览器API吗? 我不应该像 NextJS 13 之前那样使用
useEffect

我尝试添加常规检查

if (typeof window === 'undefined')
,但最终
localStorage
也未定义。

我还尝试将

List
父级转换为服务器组件,并在必要时将其所有依赖组件都作为客户端组件,但最终变得臃肿且无用。

reactjs browser server-side-rendering next.js13
1个回答
0
投票

我相信“使用客户端”仍然会在服务器上渲染您的组件一次,然后再在客户端上再次渲染。使用仅限客户端的 npm 包、动态导入客户端组件或包装在 useEffect 中应该可以解决问题。这是他们谈论客户端组件渲染的下一个文档:https://nextjs.org/docs/app/building-your-application/rendering/client-components,这里是他们谈论仅限客户端的包https ://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment

'use client'
import 'client-only'

const DataGrid = ({entity, identifier}) => {
    ...
}

const DataGrid = dynamic(() => import("./DataGrid"), { ssr: false });

const List = (props) => (
   <DataGrid>...</DataGrid>
)

useEffect(() => {
    const gridIdentifier = `${window.location.pathname}-${entity}`;
    const gridSettings = JSON.parse(localStorage.getItem(gridIdentifier) || '{}');
}, []}
© www.soinside.com 2019 - 2024. All rights reserved.