如果在一个.tsx文件中使用了”use client”,那么ssr是如何发生的?

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

How does ssr is happening if I have used "use client" in a tsx file?

问题

我刚刚开始使用nextJS 13.4.12,目前正在将一个项目从React迁移到nextJS。在处理登录页面时,我发现nextJS不允许在服务器端组件上使用react-hook-form@hookform/resolvers/yup。为了让它们工作,你需要在组件的顶部添加use client。我也这样做了。

但令我惊讶的是,当我查看网络请求时,我仍然可以看到基本的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

这是因为在最新版本的Next.js中,每个组件都会首先在服务器端进行渲染,而不管你使用了什么指令。请参考这里了解更多信息。

英文:

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.html
匿名

发表评论

匿名网友

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

确定