如何在一个.tsx文件中使用了”use client”时发生ssr?

huangapple go评论112阅读模式
英文:

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.
如何在一个.tsx文件中使用了”use client”时发生ssr?

Here is my code

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

// React Imports
&#39;use client&#39;;
import Link from &#39;next/link&#39;;
import { useForm, Controller } from &#39;react-hook-form&#39;;
import &#39;./login.css&#39;;
import Image from &#39;next/image&#39;;
// Resolvers &amp; Schema
import { yupResolver } from &#39;@hookform/resolvers/yup&#39;;
import { signupSchema } from &#39;@/schema/auth&#39;;
// Others
import { headerNameLogo } from &#39;@/EntryFile/imagePath&#39;;
import Head from &#39;next/head&#39;;
export default function Login() {
const {
handleSubmit,
control,
setError,
clearErrors,
formState: { errors, isValid },
} = useForm({
mode: &#39;onChange&#39;,
resolver: yupResolver(signupSchema),
});
return (
&lt;&gt;
&lt;Head&gt;
&lt;title&gt;Login - HRXpress&lt;/title&gt;
&lt;meta name=&quot;description&quot; content=&quot;Login page&quot; /&gt;
&lt;script src=&quot;./togglePassword.ts&quot;&gt;&lt;/script&gt;
&lt;/Head&gt;
&lt;div className=&quot;account-content&quot;&gt;
&lt;div className=&quot;container&quot;&gt;
{/* Account Logo */}
&lt;div className=&quot;account-logo&quot; style={{ marginTop: 70 }}&gt;
&lt;Link href=&quot;/app/main/dashboard&quot;&gt;
&lt;Image
style={{ width: &#39;auto&#39;, mixBlendMode: &#39;darken&#39; }}
src={headerNameLogo}
alt=&quot;HRXpress&quot;
/&gt;
&lt;/Link&gt;
&lt;/div&gt;
{/* /Account Logo */}
&lt;div className=&quot;account-box&quot;&gt;
&lt;div className=&quot;account-wrapper&quot;&gt;
&lt;h3 className=&quot;account-title&quot;&gt;Login&lt;/h3&gt;
&lt;p className=&quot;account-subtitle&quot;&gt;Access to our dashboard&lt;/p&gt;
{/* Account Form */}
&lt;div&gt;
&lt;form
onSubmit={(e) =&gt; {
e.preventDefault();
}}
&gt;
&lt;div className=&quot;form-group&quot;&gt;
&lt;label&gt;Email Address&lt;/label&gt;
&lt;Controller
name=&quot;email&quot;
control={control}
render={({ field: { value, onChange } }) =&gt; (
&lt;input
className={`form-control  ${
errors?.email ? &#39;error-input&#39; : &#39;&#39;
}`}
type=&quot;text&quot;
value={value}
onChange={onChange}
autoComplete=&quot;false&quot;
/&gt;
)}
defaultValue=&quot;admin@dreamguys.co.in&quot;
/&gt;
&lt;small&gt;{errors?.email?.message}&lt;/small&gt;
&lt;/div&gt;
&lt;div className=&quot;form-group&quot;&gt;
&lt;div className=&quot;row&quot;&gt;
&lt;div className=&quot;col&quot;&gt;
&lt;label&gt;Password&lt;/label&gt;
&lt;/div&gt;
&lt;div className=&quot;col-auto&quot;&gt;
&lt;Link className=&quot;text-muted&quot; href=&quot;/forgotpassword&quot;&gt;
Forgot password?
&lt;/Link&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;Controller
name=&quot;password&quot;
control={control}
render={({ field: { value, onChange } }) =&gt; (
&lt;div className=&quot;pass-group&quot;&gt;
&lt;input
type=&quot;password&quot;
className={`form-control  ${
errors?.password ? &#39;error-input&#39; : &#39;&#39;
}`}
value={value}
onChange={onChange}
autoComplete=&quot;false&quot;
/&gt;
&lt;span
id=&quot;togglePassword&quot;
className=&quot;fa toggle-password fa-eye&quot;
/&gt;
&lt;/div&gt;
)}
defaultValue=&quot;123456&quot;
/&gt;
&lt;small&gt;{errors?.password?.message}&lt;/small&gt;
&lt;/div&gt;
&lt;div className=&quot;form-group text-center&quot;&gt;
&lt;button
disabled={!isValid}
className=&quot;btn btn-primary account-btn&quot;
type=&quot;submit&quot;
&gt;
Login
&lt;/button&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;div className=&quot;account-footer&quot;&gt;
&lt;p&gt;
Don&#39;t have an account yet?{&#39; &#39;}
&lt;Link href=&quot;/register&quot;&gt;Register&lt;/Link&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/&gt;
);
}

<!-- 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.

huangapple
  • 本文由 发表于 2023年8月9日 17:09:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866210-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定