Next.js 13.4.4同时使用Server Action与Middleware时加载失败
问题:带Server Action的客户端表单在Middleware作用下渲染失败
当使用标记"use client"的表单搭配Server Action函数时,若Middleware作用于该表单所在路由,应用会渲染失败并报错:
客户端表单代码(page.jsx)
"use client" import { Container, Avatar, Button, CssBaseline, TextField, FormControlLabel, Checkbox, Link, Grid, Box, Typography, } from 'components/mui'; import { peformSubmit } from './formSubmit'; export const SignInSide = () => { const action = async (e) => { await peformSubmit(e) } return ( <Container component="main" maxWidth="xs"> <CssBaseline /> <Box sx={{ marginTop: 8, display: 'flex', flexDirection: 'column', alignItems: 'center', }} > <Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}> </Avatar> <Typography component="h1" variant="h5"> Sign in </Typography> <Box component={"form"} action={action} noValidate sx={{ mt: 1 }} method={"null"}> <TextField margin="normal" required fullWidth id="email" label="Email Address" name="email" autoComplete="email" autoFocus /> <TextField margin="normal" required fullWidth name="password" label="Password" type="password" id="password" autoComplete="current-password" /> <FormControlLabel control={<Checkbox value="remember" color="primary" />} label="Remember me" /> <Button type="submit" fullWidth variant="contained" sx={{ mt: 3, mb: 2 }} > Sign In </Button> <Grid container> <Grid item xs> <Link href="#" variant="body2"> Forgot password? </Link> </Grid> <Grid item> <Link href="#" variant="body2"> {"Don't have an account? Sign Up"} </Link> </Grid> </Grid> </Box> </Box> </Container> ); }; SignInSide.needAuth = false; export default SignInSide;
Server Action代码(peformSubmit.js)
'use server'; export async function peformSubmit (formData){ console.log({ email: formData.get('email'), password: formData.get('password'), }); };
Middleware代码(middleware.js)
import { NextResponse } from "next/server"; import { needAuth as _needAuth } from "./lib/needAuth"; import { AUTH } from 'routes'; export const config = { matcher: ["/auth"] } export async function middleware(request) { const needAuth = await _needAuth(request) console.log(request.url) if(needAuth){ return NextResponse.redirect(new URL('/auth', request.url)) } return NextResponse.next() }
MUI组件导出代码(components/mui/index.js)
"use client"; export * from "@mui/material";
测试情况
- 移除表单的
action属性后,应用可正常运行; - 移除Middleware(或在匹配规则中排除该页面)后,应用可正常运行;
- 即使Middleware仅保留
console.log并返回NextResponse.next(),仍会出现相同错误。
期望目标
实现表单结合Server Action正常工作,同时使用Middleware保护路由访问。示例中的匹配规则使用"/auth"仅为测试,实际需求是让其他表单也能在Middleware保护下正常工作。
package.json内容
{ "name": "authTest", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@emotion/react": "^11.11.0", "@emotion/styled": "^11.11.0", "@mswjs/data": "^0.13.0", "@mui/icons-material": "^5.11.16", "@mui/material": "^5.13.4", "bcrypt": "^5.1.0", "eslint": "8.42.0", "eslint-config-next": "13.4.4", "mongoose": "^7.2.1", "next": "13.4.4", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@types/bcryptjs": "^2.4.2" } }
内容的提问来源于stack exchange,提问作者Facundo E. Villagra
相关产品推荐
相关产品推荐

