首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当结果到达客户端时,下一个JS服务端渲染是如何工作的?

当结果到达客户端时,下一个JS服务端渲染是如何工作的?
EN

Stack Overflow用户
提问于 2020-04-15 05:15:03
回答 1查看 5.8K关注 0票数 1

我在NextJS应用程序中遇到问题。

_app.js文件中,我实例化了一个Context (它又实例化了一个State)

在我的页面ContextTest中,我声明了一个getServerSideProps()

这将从API返回一些数据,这些数据被传递给_app.js并保存到Context's state中。

到目前为止,我已经获得了所需的数据。

然后转到目标页面组件,该组件读取上下文的状态并设置一个变量。该组件成功地输出了我的变量,该变量的格式为

代码语言:javascript
复制
let userName = userState.username ? userState.username : 'Guest' 

当页面加载时,我检查来自请求的HTML值,实际上我有userState.username值。

但是浏览器中显示的超文本标记语言具有Guest

有两件事需要注意:

1)服务器端按照预期呈现2)在客户端为该页面再次执行应用程序(那么我为什么要呈现应用程序服务器端呢?)结果是这个页面没有getServerSideProps()的结果,所以我的状态是空的,并且我在控制台中得到一个警告。3)浏览器中显示的HTML是React app客户端执行的结果。(为什么?)

__app.js

代码语言:javascript
复制
import React, {useContext} from "react";
import {UserContext} from "../lib/Context/UserContext"

export default function RankerApp({Component, pageProps}) {
    const [userState, setUserState] = useContext(UserContext)();
    const [listState, setListState] = useContext(ListContext)();

    if (pageProps.serverContext && pageProps.serverContext.user) {
        setUserState({...userState, ...pageProps.serverContext.user})
    }
    delete pageProps['serverContext'];

    return (
        <ListContext.Provider value={[listState, setListState]}>
            <UserContext.Provider value={[userState, setUserState]}>
                <Component {...pageProps} />
            </UserContext.Provider>
        </ListContext.Provider>
    );
}

pages/contextTest.js

代码语言:javascript
复制
import React, {useContext} from 'react';
import {UserContext} from "../lib/Context/UserContext";
import Link from "next/link";
import UserContextSeeder from "../lib/User/UserContextSeeder";

export default function ContextPage1(props) {

    let [userState, setUserState] = useContext(UserContext);

    const currentLoggedInUserData = userState.loggedInUserId ? userState.users[userState.loggedInUserId] : null;
    const currentLoggedInUserName = currentLoggedInUserData ? currentLoggedInUserData.userName : 'Guest';

    return (
        <div>
            <h1>Page 1</h1>
            <Link href="contextTest2">
                <a>Page 2</a>
            </Link>
            <h1>Current Logged In User: {currentLoggedInUserName}</h1>
        </div>
    );
}

export async function getServerSideProps(context) {
    let userContext = {};
    // await UserContextSeeder(context).then(context => {userContext = context}); commented for simplicty
    userContext = {loggedInUserId: 222, users: {222: {userName: "Jorge"}}; // suppose this is the result 
    return {
        props: {
            serverContext: {
                user: {...userContext}
            }
        },
    }
}

更多背景信息:https://github.com/zeit/next.js/discussions/11871

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-15 05:39:09

让我们考虑一个NextJS没有水合的世界。您已经从服务器构建了DOM并将其发送到客户端,客户端显示了HTML,每个人都很高兴。现在React必须执行一个useEffect,这将触发DOM中的一些更改,但是如果React没有DOM,它将如何与虚拟DOM进程进行比较?

因此,即使我们已经在服务器上完成了,我们也需要在客户机上完成一个水合/渲染过程。服务器端渲染不是一个让浏览器省去一些工作的过程,它是我们如何确保内容提前准备好让用户和机器人看到的过程。

Josh Comeau在his blog上有一个很好的解释。

换句话说,让我们看看这段代码:

代码语言:javascript
复制
if (pageProps.serverContext && pageProps.serverContext.user) {
   setUserState({...userState, ...pageProps.serverContext.user})
}
delete pageProps['serverContext'];

return ();

这在这里被称为side effect,并且在render中执行。虽然这在正常的反应中是有效的,但在StrictMode中是被禁止的,并且会随着悬念而中断(它在正常情况下也可以中断)。因此,我们将其移动到useEffect

代码语言:javascript
复制
useEffect(() => {
  if (pageProps.serverContext && pageProps.serverContext.user) {
   setUserState(prevUserState => ({...prevUserState, ...pageProps.serverContext.user}));
  }
}, [])

请注意,我不会删除页面属性,因为我们不需要这样做。useEffect只在客户机上执行,因此它的影响将只在客户机上显现。如果您希望它们在第一次渲染时显示,则必须使用属性来渲染用户名。示例:

代码语言:javascript
复制
const [userState, setUserState] = useContext(UserContext)(props.serverContext ? props.serverContext.user : null);

在上下文钩子中:

代码语言:javascript
复制
const initialState = {
    loggedInUserId: undefined,
    users: {}
}

const userContextUpdater = (initialUser) => {
    let [state, setState] = useState({
      ...initialState,
      users: initialUser || initialStateusers,
    })
    return [state, setState];
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61217361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档