Как я могу передать данные из корневого макета всем элементам в приложении Next.js?

Вопрос или проблема

Я получаю локализацию через API. Они представляют собой массив объектов с ключами и значениями.

Согласно Next.js, невозможно передать данные от родительского компонента к дочернему, поэтому я решил использовать следующий подход:


const _localization = (await post_req(process.env.LANG_GET_TRANSLATELIST,false,{AddLang: true,list:TranslationByPage},false)).data?.Data?.list;

   return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} ${yekan.variable} antialiased`}
      >
        <ConfigProvider _settings={_localization}>{children}</ConfigProvider>
      </body>
    </html>

Но, как вы можете заметить, мне нужно использовать провайдер контекста React, а это хук. Поэтому мне нужно сделать каждый компонент в моем приложении клиентским компонентом, чтобы иметь возможность использовать локализацию.

Я создал хук, как вы можете видеть:


export default function useLanguage(formKey) {
  const { _settings } = useContext(WAConfigContext);
  const _languages = _settings && _settings?.find((el) => Array.isArray(el));
  const _value = _languages && _languages.find((el) => el.FormKey === formKey);

  return _value?.Value || _value?.Key;
}

Но я хочу изменить это. Это всего лишь однократные данные, которые я получаю один раз и проверяю каждые 24 часа.

Я хочу иметь возможность передавать эти локализации без провайдера контекста, чтобы мне не нужно было делать мои компоненты клиентскими компонентами.

Мне бы хотелось, чтобы был способ иметь проп во всех моих файлах page.jsx, называемый languages, например. И я мог бы фильтровать их с помощью обычной функции, а не хука.

Согласно документации next.js: Смотрите ссылку

Если вы используете fetch, запросы автоматически кэшируются. Это означает, что вы можете безопасно несколько раз вызывать один и тот же URL с одинаковыми параметрами, и будет выполнен только один запрос.

Вы можете написать общую функцию для вызова API с использованием fetch и вызываться этой функции в других местах

// utils.ts
export async function getSettings() {
  const res = await fetch(...);
  const settings = await res.json();
  return settings;
}

// layout.tsx
import { getSettings } from './utils';

export default async function PageLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const settings = await getSettings();
  return (
    <div>{children}</div>
  );
}

// page.tsx
import { getSettings } from './utils';

export default async function HomePage() {
  const settings = await getSettings();
  return (
    <div>hello</div>
  );
}

.

Ответ или решение

Чтобы передать данные из корневого макета ко всем элементам в приложении Next.js, которое делает запросы для локализации, существует несколько подходов. Ваша цель — избежать использования контекстного провайдера, который требует, чтобы каждый компонент являлся клиентским, сделав тем самым вашу архитектуру более простой и удобной для обслуживания.

1. Использование серверного рендеринга и получения данных

Первый и наиболее подходящий способ — это воспользоваться возможностями серверного рендеринга (SSR) в Next.js. Это позволит вам загружать данные на сервере и передавать их как пропсы в ваши страницы и компоненты.

Пример использования SSR для получения локализации:

// utils.js
export async function fetchLocalization() {
  const response = await fetch(`${process.env.LANG_GET_TRANSLATELIST}?AddLang=true`);
  const data = await response.json();
  return data.Data?.list || [];
}

// layout.tsx
import { fetchLocalization } from './utils';

export default async function RootLayout({ children }) {
  const localizations = await fetchLocalization();

  return (
    <html lang="en">
      <body>
        {React.cloneElement(children, { languages: localizations })}
      </body>
    </html>
  );
}

// page.jsx
export default function Home({ languages }) {
  const localization = languages.find(lang => lang.FormKey === 'someKey');

  return (
    <div>
      {localization ? localization.Value : 'Локализация не найдена!'}
    </div>
  );
}

2. Применение статической генерации (SSG)

Если ваши данные локализации не меняются очень часто (например, раз в 24 часа), вы можете использовать статическую генерацию с помощью getStaticProps. Это позволит вам предзагрузить данные во время сборки сайта.

Пример статической генерации:

// [page].jsx
export async function getStaticProps() {
  const localizations = await fetchLocalization();
  return {
    props: {
      languages: localizations,
    },
    revalidate: 86400, // обновляет раз в 24 часа
  };
}

export default function Home({ languages }) {
  return (
    <div>
      {/* Используйте языковые данные здесь */}
    </div>
  );
}

3. Распространение пропсов ко всем компонентам

Чтобы пробросить ваши данные ко всем дочерним компонентам без использования контекста, вы можете использовать React.cloneElement(), позволяя передавать пропсы всем дочерним элементам родительского компонента, как показано выше.

Заключение

Следуя этим подходам, вы сможете эффективно передавать локализацию по всему приложению Next.js, избегая ненужных зависимостей от контекста и лишних ререндеров. Использование SSR или SSG также обеспечит быстрое время загрузки и хорошее взаимодействие с пользователем, что является критически важным в современных веб-приложениях.

Помните, важность SEO оптимизации не следует недооценивать, так как правильное использование данных локализации и серверного рендеринга улучшает индексируемость ваших страниц, что в конечном итоге приводит к более высокой видимости в поисковых системах.

Оцените материал
Добавить комментарий

Капча загружается...