admin管理员组文章数量:1327849
I am having a problem in NextJS app.
In the _app.js
file I instantiate a Context
(which in turns instantiates a State
)
In my page ContextTest
I declare a getServerSideProps()
.
This returns some data from an API, that is passed to the _app.js
and saved into Context's state
.
So far, I have the data that I need.
Then it goes to the target page ponent, the ponent reads the context's state and sets a variable. The ponent successfully outputs my variable, which is in the form
let userName = userState.username ? userState.username : 'Guest'
When page loads, I inspect the HTML from the request and indeed I have userState.username
value.
But then the shown HTML in the browser has Guest
.
There are two things to note:
1) The server side renders as expected
2) The App is executed again in the client for that page (so why did I render the app server side then?). The result is that this page doesn't have the result of getServerSideProps()
so my state is empty and I get a warning in console.
3) The HTML displayed in the browser is the one resulting of client execution of React app. (Why?)
__app.js
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
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}); mented for simplicty
userContext = {loggedInUserId: 222, users: {222: {userName: "Jorge"}}; // suppose this is the result
return {
props: {
serverContext: {
user: {...userContext}
}
},
}
}
More context: .js/discussions/11871
I am having a problem in NextJS app.
In the _app.js
file I instantiate a Context
(which in turns instantiates a State
)
In my page ContextTest
I declare a getServerSideProps()
.
This returns some data from an API, that is passed to the _app.js
and saved into Context's state
.
So far, I have the data that I need.
Then it goes to the target page ponent, the ponent reads the context's state and sets a variable. The ponent successfully outputs my variable, which is in the form
let userName = userState.username ? userState.username : 'Guest'
When page loads, I inspect the HTML from the request and indeed I have userState.username
value.
But then the shown HTML in the browser has Guest
.
There are two things to note:
1) The server side renders as expected
2) The App is executed again in the client for that page (so why did I render the app server side then?). The result is that this page doesn't have the result of getServerSideProps()
so my state is empty and I get a warning in console.
3) The HTML displayed in the browser is the one resulting of client execution of React app. (Why?)
__app.js
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
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}); mented for simplicty
userContext = {loggedInUserId: 222, users: {222: {userName: "Jorge"}}; // suppose this is the result
return {
props: {
serverContext: {
user: {...userContext}
}
},
}
}
More context: https://github./zeit/next.js/discussions/11871
Share asked Apr 14, 2020 at 21:15 JorgeeFGJorgeeFG 6,00113 gold badges64 silver badges100 bronze badges1 Answer
Reset to default 6Let's consider a world where NextJS did not hydrate. You have build the DOM from the server and sent it to the client, client showed the HTML, everyone is happy. Now React has to execute a useEffect
which will trigger some change in the DOM, but if React does not have the DOM, how would it look do the parison the virtual DOM process?
So, we need a hydration/render process on the client even if we have already done it on the server. Server side rendering is not a process by which we spare the browser some jobs, it is how we make sure content is ready early for the user and bots to see.
Josh Comeau has a nice explanation on his blog.
On a different note, let's look at this code:
if (pageProps.serverContext && pageProps.serverContext.user) {
setUserState({...userState, ...pageProps.serverContext.user})
}
delete pageProps['serverContext'];
return ();
This here is called a side effect and one which is being executed in render
. While this works with normal React, it is prohibited in StrictMode and will break with Suspense (it can also break in normal cases). So we move this to a useEffect
.
useEffect(() => {
if (pageProps.serverContext && pageProps.serverContext.user) {
setUserState(prevUserState => ({...prevUserState, ...pageProps.serverContext.user}));
}
}, [])
Note that I'm not deleting the page prop, because we don't need to.
useEffect
is only executed on the client, so the effects of this are going to show up only on the client. If you want them to show up on the first render, you would have to use the prop to render username. Example:
const [userState, setUserState] = useContext(UserContext)(props.serverContext ? props.serverContext.user : null);
In context hook:
const initialState = {
loggedInUserId: undefined,
users: {}
}
const userContextUpdater = (initialUser) => {
let [state, setState] = useState({
...initialState,
users: initialUser || initialStateusers,
})
return [state, setState];
}
本文标签: javascriptHow does Next JS server side rendering works when result hits clientStack Overflow
版权声明:本文标题:javascript - How does Next JS server side rendering works when result hits client? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742220088a2435290.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论