Nextjs - 在 _app init 上获取 cookies 值
Nextjs - getting cookies value on _app init
我需要在第一次呈现时获取 cookie 值。我得到了 _app.tsx 中的那些。
一切看起来都很好(正确呈现 html)但我收到 server/client 不匹配警告,因为在服务器上的第一次呈现时,cookie 未定义并且值回落到默认值 0。
在水合时,该值是从 cookie 中选取的并正确显示。
有人可以向我解释为什么服务器上的值是默认值的问题(因此我收到此警告)以及编写此代码的更好方法是什么?
这是我的_app.tsx
import React, { useState, useEffect } from 'react'
import type { AppProps } from 'next/app'
import { UserContext } from '../context/UserContext'
require('es6-promise').polyfill()
let cookieHelper
if (typeof window !== 'undefined') {
cookieHelper = require( '../helpers/_cookies' ) // This is a file written by us where we export const and get/set cookies func
}
function ElliotApp ({ Component, pageProps }: AppProps) {
useEffect(() => {
import('../helpers/_cookies')
}, [])
const searchesFromCookies = cookieHelper?.get(cookieHelper?.COOKIE_NAME_SEARCH_COUNT) // this value is a string like '3'
const userState = {
numOfSearches: searchesFromCookies || 0
}
const [userContext, setUserContext] = useState(userState)
useEffect(() => {
cookieHelper?.set(cookieHelper?.COOKIE_NAME_SEARCH_COUNT, userContext.numOfSearches)
}, [userContext])
return (
<UserContext.Provider value={[userContext, setUserContext]}>
<Component {...pageProps} />
</UserContext.Provider>
)
}
export default ElliotApp
非常感谢!
Could someone explain to me why is a problem that on the server the value is the default value
可能是因为您的 cookieHelper
只是从 document.cookie
读取 cookie 而服务器上没有这样的东西。
如果你想通过 SSR 获取 cookie,你可以使用 getInitialProps
:
function parseCookies(req) {
// cookie.parse is some function that accepts cookie string and return parsed object
return cookie.parse(req ? req.headers.cookie || "" : document.cookie)
}
ElliotApp.getInitialProps = async ({ req }) => {
const cookies = parseCookies(req)
return {
searchesFromCookies: cookies[COOKIE_NAME_SEARCH_COUNT]
}
}
然后在您的 App 组件中对它们执行一些操作:
function ElliotApp ({ Component, pageProps, searchesFromCookies }: AppProps) {
const userState = {
numOfSearches: searchesFromCookies || 0
}
const [userContext, setUserContext] = useState(userState)
// do whatever ...
}
编辑:
如果您对服务器上的默认值没问题,那么您只需要在 useEffect
挂钩中执行所有操作(它不会 运行 在服务器上):
function ElliotApp ({ Component, pageProps }: AppProps) {
const userState = {
numOfSearches: 0
}
const [userContext, setUserContext] = useState(userState)
useEffect(() => {
setUserContext({
numOfSearches: cookieHelper.get(cookieHelper.COOKIE_NAME_SEARCH_COUNT)
});
}, []);
useEffect(() => {
cookieHelper.set(cookieHelper.COOKIE_NAME_SEARCH_COUNT, userContext.numOfSearches)
}, [userContext])
return (
<UserContext.Provider value={[userContext, setUserContext]}>
<Component {...pageProps} />
</UserContext.Provider>
)
}
我需要在第一次呈现时获取 cookie 值。我得到了 _app.tsx 中的那些。 一切看起来都很好(正确呈现 html)但我收到 server/client 不匹配警告,因为在服务器上的第一次呈现时,cookie 未定义并且值回落到默认值 0。 在水合时,该值是从 cookie 中选取的并正确显示。
有人可以向我解释为什么服务器上的值是默认值的问题(因此我收到此警告)以及编写此代码的更好方法是什么?
这是我的_app.tsx
import React, { useState, useEffect } from 'react'
import type { AppProps } from 'next/app'
import { UserContext } from '../context/UserContext'
require('es6-promise').polyfill()
let cookieHelper
if (typeof window !== 'undefined') {
cookieHelper = require( '../helpers/_cookies' ) // This is a file written by us where we export const and get/set cookies func
}
function ElliotApp ({ Component, pageProps }: AppProps) {
useEffect(() => {
import('../helpers/_cookies')
}, [])
const searchesFromCookies = cookieHelper?.get(cookieHelper?.COOKIE_NAME_SEARCH_COUNT) // this value is a string like '3'
const userState = {
numOfSearches: searchesFromCookies || 0
}
const [userContext, setUserContext] = useState(userState)
useEffect(() => {
cookieHelper?.set(cookieHelper?.COOKIE_NAME_SEARCH_COUNT, userContext.numOfSearches)
}, [userContext])
return (
<UserContext.Provider value={[userContext, setUserContext]}>
<Component {...pageProps} />
</UserContext.Provider>
)
}
export default ElliotApp
非常感谢!
Could someone explain to me why is a problem that on the server the value is the default value
可能是因为您的 cookieHelper
只是从 document.cookie
读取 cookie 而服务器上没有这样的东西。
如果你想通过 SSR 获取 cookie,你可以使用 getInitialProps
:
function parseCookies(req) {
// cookie.parse is some function that accepts cookie string and return parsed object
return cookie.parse(req ? req.headers.cookie || "" : document.cookie)
}
ElliotApp.getInitialProps = async ({ req }) => {
const cookies = parseCookies(req)
return {
searchesFromCookies: cookies[COOKIE_NAME_SEARCH_COUNT]
}
}
然后在您的 App 组件中对它们执行一些操作:
function ElliotApp ({ Component, pageProps, searchesFromCookies }: AppProps) {
const userState = {
numOfSearches: searchesFromCookies || 0
}
const [userContext, setUserContext] = useState(userState)
// do whatever ...
}
编辑:
如果您对服务器上的默认值没问题,那么您只需要在 useEffect
挂钩中执行所有操作(它不会 运行 在服务器上):
function ElliotApp ({ Component, pageProps }: AppProps) {
const userState = {
numOfSearches: 0
}
const [userContext, setUserContext] = useState(userState)
useEffect(() => {
setUserContext({
numOfSearches: cookieHelper.get(cookieHelper.COOKIE_NAME_SEARCH_COUNT)
});
}, []);
useEffect(() => {
cookieHelper.set(cookieHelper.COOKIE_NAME_SEARCH_COUNT, userContext.numOfSearches)
}, [userContext])
return (
<UserContext.Provider value={[userContext, setUserContext]}>
<Component {...pageProps} />
</UserContext.Provider>
)
}