0

所以,情况就是这样。

我正在尝试在应用程序初始化中获取“语言”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()执行。

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

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”,因为根据文档......

“这会禁用执行自动静态优化的能力,导致应用程序中的每个页面都在服务器端呈现。”

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

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

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

任何帮助表示赞赏。

4

2 回答 2

1

我不确定这是否有帮助,但可能有一种方法可以避免闪烁。Next.js 实际上没有默认为 English / LTR,而是具有可配置的i18n 路由,它尝试使用浏览器标头检测用户的首选语言环境。甚至还有cookie 支持,但它必须是硬编码的NEXT_LOCALEcookie。

即使您已经探索过该解决方案,我也会将其留给其他有类似问题的人。

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

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

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

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

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

这不会导致任何布局闪烁。

再次感谢@Summer 的帮助。

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

PS:我决定编辑该答案以给予@Summer 荣誉。

于 2022-01-07T17:21:21.683 回答
0

当前不支持使用getServerSideProps()on 。_app.tsx

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

于 2022-01-07T17:25:46.953 回答