英文:
How does ssr is happening if I have used "use client" in a tsx file?
问题
I have just started working on nextJS 13.4.12 and currently shifting a project from react to nextJS. While working on the login page I found that nextJS does not allow to use react-hook-form
or @hookform/resolvers/yup
on server-side components. For them to work you need to add use client
at the very top of the component. And I also did that.
但是令我惊讶的是,当我查看网络请求时,仍然可以看到包含输入框、按钮和其他一些标签的基本HTML代码。这里是如何进行服务器端渲染的呢?
PS:我已经看过很多文章、教程、代码片段和文档。它们直接使用了hook-form和yupresolver,而没有实际指定use client
。尽管它们大多是使用13.0.5。
以下是我的代码:
// React Imports
'use client';
import Link from 'next/link';
import { useForm, Controller } from 'react-hook-form';
import './login.css';
import Image from 'next/image';
// Resolvers & Schema
import { yupResolver } from '@hookform/resolvers/yup';
import { signupSchema } from '@/schema/auth';
// Others
import { headerNameLogo } from '@/EntryFile/imagePath';
import Head from 'next/head';
export default function Login() {
const {
handleSubmit,
control,
setError,
clearErrors,
formState: { errors, isValid },
} = useForm({
mode: 'onChange',
resolver: yupResolver(signupSchema),
});
return (
<>
<Head>
<title>Login - HRXpress</title>
<meta name="description" content="Login page" />
<script src="./togglePassword.ts"></script>
</Head>
<div className="account-content">
<div className="container">
{/* Account Logo */}
<div className="account-logo" style={{ marginTop: 70 }}>
<Link href="/app/main/dashboard">
<Image
style={{ width: 'auto', mixBlendMode: 'darken' }}
src={headerNameLogo}
alt="HRXpress"
/>
</Link>
</div>
{/* /Account Logo */}
<div className="account-box">
<div className="account-wrapper">
<h3 className="account-title">Login</h3>
<p className="account-subtitle">Access to our dashboard</p>
{/* Account Form */}
<div>
<form
onSubmit={(e) => {
e.preventDefault();
}}
>
<div className="form-group">
<label>Email Address</label>
<Controller
name="email"
control={control}
render={({ field: { value, onChange } }) => (
<input
className={`form-control ${
errors?.email ? 'error-input' : ''
}`}
type="text"
value={value}
onChange={onChange}
autoComplete="false"
/>
)}
defaultValue="admin@dreamguys.co.in"
/>
<small>{errors?.email?.message}</small>
</div>
<div className="form-group">
<div className="row">
<div className="col">
<label>Password</label>
</div>
<div className="col-auto">
<Link className="text-muted" href="/forgotpassword">
Forgot password?
</Link>
</div>
</div>
<Controller
name="password"
control={control}
render={({ field: { value, onChange } }) => (
<div className="pass-group">
<input
type="password"
className={`form-control ${
errors?.password ? 'error-input' : ''
}`}
value={value}
onChange={onChange}
autoComplete="false"
/>
<span
id="togglePassword"
className="fa toggle-password fa-eye"
/>
</div>
)}
defaultValue="123456"
/>
<small>{errors?.password?.message}</small>
</div>
<div className="form-group text-center">
<button
disabled={!isValid}
className="btn btn-primary account-btn"
type="submit"
>
Login
</button>
</div>
</form>
<div className="account-footer">
<p>
Don't have an account yet?{' '}
<Link href="/register">Register</Link>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}
英文:
I have just started working on nextJS 13.4.12 and currently shifting a project from react to nextJS. While working on the login page I found that nextJS does not allow to use react-hook-form
or @hookform/resolvers/yup
on server-side components. For them to work you need to add use client
at the very top of the component. And I also did that.
But to my surprise when I see the network request I can still see the basic HTML code consisting of input, buttons, and some other tags as well.
How does ssr happening here?
PS: I have seen a ton of articles, tutorials, snippets, and docs. They were directly using hook-form, yupresolver without actually specifying use client
. Although they were mostly using 13.0.5.
Here is my code
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
// React Imports
'use client';
import Link from 'next/link';
import { useForm, Controller } from 'react-hook-form';
import './login.css';
import Image from 'next/image';
// Resolvers & Schema
import { yupResolver } from '@hookform/resolvers/yup';
import { signupSchema } from '@/schema/auth';
// Others
import { headerNameLogo } from '@/EntryFile/imagePath';
import Head from 'next/head';
export default function Login() {
const {
handleSubmit,
control,
setError,
clearErrors,
formState: { errors, isValid },
} = useForm({
mode: 'onChange',
resolver: yupResolver(signupSchema),
});
return (
<>
<Head>
<title>Login - HRXpress</title>
<meta name="description" content="Login page" />
<script src="./togglePassword.ts"></script>
</Head>
<div className="account-content">
<div className="container">
{/* Account Logo */}
<div className="account-logo" style={{ marginTop: 70 }}>
<Link href="/app/main/dashboard">
<Image
style={{ width: 'auto', mixBlendMode: 'darken' }}
src={headerNameLogo}
alt="HRXpress"
/>
</Link>
</div>
{/* /Account Logo */}
<div className="account-box">
<div className="account-wrapper">
<h3 className="account-title">Login</h3>
<p className="account-subtitle">Access to our dashboard</p>
{/* Account Form */}
<div>
<form
onSubmit={(e) => {
e.preventDefault();
}}
>
<div className="form-group">
<label>Email Address</label>
<Controller
name="email"
control={control}
render={({ field: { value, onChange } }) => (
<input
className={`form-control ${
errors?.email ? 'error-input' : ''
}`}
type="text"
value={value}
onChange={onChange}
autoComplete="false"
/>
)}
defaultValue="admin@dreamguys.co.in"
/>
<small>{errors?.email?.message}</small>
</div>
<div className="form-group">
<div className="row">
<div className="col">
<label>Password</label>
</div>
<div className="col-auto">
<Link className="text-muted" href="/forgotpassword">
Forgot password?
</Link>
</div>
</div>
<Controller
name="password"
control={control}
render={({ field: { value, onChange } }) => (
<div className="pass-group">
<input
type="password"
className={`form-control ${
errors?.password ? 'error-input' : ''
}`}
value={value}
onChange={onChange}
autoComplete="false"
/>
<span
id="togglePassword"
className="fa toggle-password fa-eye"
/>
</div>
)}
defaultValue="123456"
/>
<small>{errors?.password?.message}</small>
</div>
<div className="form-group text-center">
<button
disabled={!isValid}
className="btn btn-primary account-btn"
type="submit"
>
Login
</button>
</div>
</form>
<div className="account-footer">
<p>
Don't have an account yet?{' '}
<Link href="/register">Register</Link>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}
<!-- end snippet -->
答案1
得分: 1
因为在最新版本的nextJS中,每个组件首先在服务器端呈现,无论您使用了什么指令。请参考这里了解更多。
英文:
It is because in latest version of nextJS each component is firstly rendered on the server side, irrespective of directive you've used. Please refer here for more.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论