_app.tsx Next.js 中的 getServerSideProps

getServerSideProps in _app.tsx in Next.js

那么,情况是这样的。

我正在尝试在应用程序初始化中获取“语言”cookie 以相应地更改 UI。 例如,如果语言是“阿拉伯语”(ar),我会将布局恢复为“RTL”,反之亦然。

有两种方法可以实现,第一种方法是在"useEffect()"中获取cookie,像这样...

import { parseCookies } from "nookies";
import { useEffect, useLayoutEffect, useState } from "react";
import { StyleSheetManager, ThemeProvider } from "styled-components";
import rtlPlugin from "stylis-plugin-rtl";

function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
  const [appLanguage, setAppLanguage] = useState("en");

  useEffect(() => {
    const cookies = parseCookies();
    setAppLanguage(cookies.language);
  }, []);

  useEffect(() => {
    history.scrollRestoration = "manual";

    if (appLanguage === "ar") {
      document.documentElement.classList.add("rtl");
      document.documentElement.dir = "rtl";
    } else {
      document.documentElement.classList.remove("rtl");
      document.documentElement.dir = "ltr";
    }
  }, [appLanguage]);

  console.log("Appp Language", appLanguage);

  return (
    <>
      <ThemeProvider theme={theme}>
        <StyleSheetManager stylisPlugins={[rtlPlugin]}>
          <>
            <GlobalStyle />
            <SessionProvider session={session}>
              <Component {...pageProps} />
            </SessionProvider>
          </>
        </StyleSheetManager>
      </ThemeProvider>
    </>
  );
}


export default wrapper.withRedux(MyApp);

这行得通,但您可以想象的问题是,在执行 useEffect() 之前,默认“英语”布局的页面会短暂闪烁。

避免这种闪烁行为的另一种方法当然是在 _app.tsx 级别上使用 getInitialProps,就像这样...

MyApp.getInitialProps = async (appContext: AppContext) => {

  const cookies = nookies.get(appContext)
  const appLanguage = cookies.language;

  const appProps = await App.getInitialProps(appContext);

  return { appLanguage, ...appProps };
};

现在您可以在根 _app 级别上使用“appLanguage”道具来做任何您想做的事情。

这种方法的唯一问题是“Next.js”团队不建议在 _app 级别使用“getInitialProps”,因为根据文档...

"this disables the ability to perform automatic static optimization, causing every page in your app to be server-side rendered."

另一方面,您似乎无法在根 _app 级别使用“getServerSideProps”。

所以,我的问题是,如何两全其美?获取状态以从根“_app”级别共享它而不使用 getInitialProps 不让服务器端呈现每个页面?

这可能吗?或者有没有办法在根“_app”文件中使用“getServerSideProps”?

感谢任何帮助。

我不确定这是否有帮助,但可能有一种方法可以避免闪烁。 Next.js 实际上具有可配置的 i18n routing, which tries to detect the user's preferred locale using browser headers. There's even cookie support,而不是默认的英语/LTR,但它必须是硬编码的 NEXT_LOCALE cookie。

即使您已经探索过该解决方案,我也会将它留在这里供遇到类似问题的其他人使用。

============= 使用 NEXT.JS i18n 路由的解决方案 ===========

感谢@Summer 的建议,我能够使用 Next.js 内置的 i18n 路由解决方案解决我的问题,我不知道它存在。

导致 UI 闪烁的问题之所以发生,是因为我一直在等待 useEffect() 函数在 _app.tsx 中执行,以便添加某种特殊的 CSS class 或 HTML 属性标记,以便能够在 CSS 文件中定位 CSS class 并切换方向或执行任何其他操作CSS 修改。

但是现在通过使用内置的 Next.js i18n 路由,Next.js 可以通过查找“NEXT_LOCALE”cookie 或者他是否可以检测您应用程序的语言'发现他将默认为您选择的默认语言,这样做 Next.js 会自动向您的标签添加一个直接来自服务器的“lang”属性,然后您可以在您的CSS 切换布局方向...

html {
  &[lang="ar"] {
      direction: rtl;
  }
}

而且不会造成任何布局闪烁。

再次感谢@Summer 的帮助。

这是一篇关于使用 Next.js 国际化路由的好文章。 https://blog.logrocket.com/complete-guide-internationalization-nextjs/

P.S:我决定编辑该答案以感谢@Summer。

目前不支持在 _app.tsx 上使用 getServerSideProps()

您可以关注 Github 上的讨论:https://github.com/vercel/next.js/discussions/10874