使用useEffect的Nextjs页面不能进行服务器端渲染?

cgh8pdjw  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(142)

我正在考虑从react迁移到nextjs,我对服务器端渲染的理解有一些问题。
如果我的页面包含具有使用效果的组件(例如,我使用一个组件,其中有三个使用useEffect钩子的ejs),nextjs将使用客户端渲染来渲染整个页面(和react一样)而不是服务器端渲染?所以nextjs在这种情况下是无用的?同样的案子,有时候我会使用window.addEventView和useEffect来添加一些滚动效果,这样我就不能在这个组件上进行服务器端的渲染。在同一页面上创建一个混合SSR和CSR?(例如,CSR的组件使用useEffect钩子,而其他组件在同一页面上使用SSR作为静态组件)
如果我需要更新页面上的数据,例如每一秒,如果我使用SSR,HTTP请求被发送到服务器,服务器发出另一个HTTP请求来获取数据,生成另一个HTML,并将新的HTML页面与更新数据发送到客户端?在我看来,重新生成页面比直接发出客户端请求来获取数据需要更长的时间。
我希望在同一个页面上使用SSR和CSR,使用强大的SSR来生成HTML,并在同一个页面上的特定组件上使用CSR来使用NextJS产生效果(如threejs,滚动效果等),但我现在不这样做,如果可能的话。

icomxhvb

icomxhvb1#

所以有可能在同一页上制作混合SSR和CSR?
是的,我会的
如果我需要更新页面上的数据,例如每一秒,如果我使用SSR,HTTP请求被发送到服务器,服务器发出另一个HTTP请求来获取数据,生成另一个HTML并将新的HTML页面与更新数据发送到客户端?
CSR,因为页面上的其余静态内容将保持原样。如果你做SSR,整个页面将重新呈现,状态将重新初始化。如果你在页面中有useEffect,useStates...等,NextJS甚至不允许你制作该页面(它会抛出错误)

解决方案

  • 只需创建一个组件,在顶部添加'use client'指令,将该组件导入到页面中。
    这是我编写的一个小代码:
    文件夹结构:

我正在使用应用程序路由器,&我已经排除了额外的文件夹&文件.

projectName
├── src
│   └── app
│       ├── api
│       ├── comp
│       │   ├── Hybrid.js
│       ├── favicon.ico
│       ├── globals.css
│       ├── hybrid
│       │   └── page.js
│       ├── layout.js
│       ├── page.js
└── tailwind.config.js

字符串

Hybrid.jscomp文件夹projectName\src\app\comp\Hybrid.js中的组件:

'use client'
import React, { useEffect, useState } from 'react'

const Hybrid = () => {

    async function CallProductsAPI() {
        let tmp = await fetch('https://dummyjson.com/products')
        let data = await tmp.json()
        console.log("Data from API : ", data);
        // VISIBLE IN BROWSER CONSOLE
        SetProducts(data)
    }

    const [Products, SetProducts] = useState(null)

    useEffect(() => {
        CallProductsAPI()
    }, [])

    return (
        <div>
            <h1>Products Page</h1>
            {
                Products

                    ?
                    Products.products.slice(0, 5).map((p, i) => {
                        // DATA IS INSIDE products key
                        // LOTS OF DATA, HENCE slice(0,5) to show 5 results
                        return (
                            <h6 key={i} onClick={() => { alert(p.title + "Clicked !") }}>{p.title}</h6>
                        )
                    })
                    :

                    "Loading Products ...."
                // THIS LOADING STATE WILL  BE VISIBLE BECAUSE CLIENT LOADS A SECTION OF PAGE 

            }
        </div>
    )
}

export default Hybrid

page.js(文件名根据app router文件约定)projectName\src\app\hybrid\page.js

import Hybrid from "../comp/Hybrid"

const page = () => {
    return (
        <div>
            <h1>Hybrid Page</h1>

            <Hybrid />

            <h3>Rest of the page is rendered by server.</h3>
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. 
            </p>
        </div>
    )
}

export default page

说明:

  • 我做了一个Hybrid页面,它从useEffect调用API。
  • 我做了一个客户端组件,它调用API并设置状态中的数据,然后在DOM中更新。
  • 为了增加互动性,如果您点击这些产品名称警报将显示。
  • 然后我有page.js,它由服务器呈现。
  • 我在第页中导入了此组件。
    输出:
  • 转到http://localhost:3000/hybrid,打开控制台并导航到Network Tab
  • Name tab下,您将看到hybrid。单击它并在右侧单击Preview
  • 您将看到预渲染页面(SSR+CSR已实现!)。
  • 你可能想知道,Loading Products ....是如何可见的?Next.js使用React的API在服务器上为客户端和服务器组件呈现静态HTML预览。(阅读完整页面加载,下面给出的链接)
  • 请尝试删除use client并查看,错误:You're importing a component that needs useState.
  • 请阅读:*
  • 什么是React服务器组件负载(RSC)?:https://nextjs.org/docs/app/building-your-application/rendering/server-components#how-are-server-components-rendered
    ***客户端组件如何呈现?**https:nextjs.org/docs/app/building-your-application/rendering/client-components#how-are-client-components-rendered
  • 全页加载:https://nextjs.org/docs/app/building-your-application/rendering/client-components#full-page-load
  • 后续导航:https://nextjs.org/docs/app/building-your-application/rendering/client-components#subsequent-navigations
  • 如果您有任何疑问,请留下评论。

相关问题