概要
- ReactにMUIのPaperをstyled 宣言したところで次の『Server Error』エラーが発生しました。
- エラーの原因と対応の手順をまとめました。
開発環境
- React 19.0.0-rc-69d4b800-20241021
- Next.js 15.0.1
- MUI 6.1.6
エラー内容
- Next.jsのプロジェクトで
http://localhost:3000/test
のページを作成。 - 次のMUIのドキュメントページからPaperをstyled定義するコードを
page.tsx にコピーして実行したら『Server Error』が発生しました。 - コードを参考にした場所のURLは ↓ です。
https://mui.com/material-ui/react-grid2/#inheriting-spacing
src\app\test\page.tsx
import {Box, Paper} from '@mui/material';
import { styled } from '@mui/material/styles';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
export default function Home() {
return (
<Box sx={{ flexGrow: 1 }}>
<div><Item>Test</Item></div>
</Box>
);
}
参考
- Installation – Material UI
- クライアントの子コンポーネントから サーバーの親コンポーネントに 値を渡したいときはどうするか
- Next.jsのapp routerでMUIを使うとエラーが出る件について
原因
- エラー内容で確認すると、
- サーバーからdefault()をコールしようとしていますが、defaultはクライアント側にあります。
- サーバーからクライアントの関数を呼び出すことはできない。
- Component側にするか、クライアントComponentにpropsとしで渡す
- とのことでした。
Server Error
Error:
Attempted to call default() from the server but default is on the client.
It's not possible to invoke a client function from the server,
it can only be rendered as a Component or passed to props of a Client Component.
対応
- Paperのstyled定義をclientで行うために既存のPaperをstyled定義処理を削除、
client処理用ファイルstyles.tsx
を作成して移動します。
src\app\test\page.tsx
import {Box, Paper} from '@mui/material';
import { styled } from '@mui/material/styles';
// Parerをstyled定義を削除
/*
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
**/
export default function Home() {
return (
<Box sx={{ flexGrow: 1 }}>
<div className="border-solid border-2"><Item>Test</Item></div>
</Box>
);
}
src\app\test\styles.tsx
// Parerをstyled定義処理をそのまま移動
import {Paper} from '@mui/material';
import { styled } from '@mui/material/styles';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
- 続けて
styles.tsx
に次の修正を行います。- ファイルの最初に
"use client";
を追記することでクライアント側で処理することを宣言します。 page.tsx
で利用できるようにするために Paperをstyled定義の前にexport
を追記します。
- ファイルの最初に
src\app\test\styles.tsx
// クライアント側で処理することを宣言します。
"use client";
import {Paper} from '@mui/material';
import { styled } from '@mui/material/styles';
// exportを追記することでほかの場所から利用できるようにします。
export const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
- 次のimportを追記して
styles.tsx
から定義したItemを呼び出します。 - Itemを呼び出す
styles.tsx
のパスは .tsxは付けない
ことに注意してください。
import {Item} from './styles';
src\app\test\page.tsx
import {Box} from '@mui/material';
// styles.tsxからItemを呼び出します。
import {Item} from './styles';
export default function Home() {
return (
<Box sx={{ flexGrow: 1 }}>
<div className="border-solid border-2"><Item>Test</Item></div>
</Box>
);
}
- これで
http://localhost:3000/test
に接続すると次のように画面が正常に表示されました。