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>
  )
}