Передавать данные (prop) из _app.js чтобы получить serversideprops на странице — NextJS, последняя версия

#javascript #node.js #reactjs #next.js

#javascript #node.js #reactjs #next.js

Вопрос:

У меня есть пользовательский _app.js :

   const Layout = ({ children }) => (children);

  const app = ({ Component, pageProps }) => {

    pageProps.baseUrl = 'some url';

    return (
      <Layout>
        <Component {...pageProps} />
      </Layout>
    )
};
 

И страница:

 export async function getServerSideProps({ req, query, res, baseUrl }) { 
// baseUrl is undefined and an error, if I am using it with destructiring

  console.log(req) // There is no baseUrl

  return { props: { ..... } }
}
 

Я хочу установить это pageProps.baseUrl= 'some url'; _app.js и использовать его в компонентах страницы, в том числе getServerSideProps , как я могу это сделать?

Ответ №1:

На данный момент я создал файл, который содержит все глобальные значения, подобные этому:

 let store = {};

const globalStore = {};

globalStore.set = (key, value) => {
    store = { ...store, [key]: value };
}

globalStore.get = (key) => {
    return store[key];
}


export default globalStore;
 

Затем _app.js импортируйте его и задайте значение:

 const app = ({ Component, pageProps }) => {
    globalStore.set('baseUrl', 'some url 1');
    globalStore.set('baseUrl2', 'some url 2');

    return (
        <Layout>
            <Component {...pageProps} />
        </Layout>
    )
}
 

импортируйте файл в pages/index.js и внутри компонента или getServerSideProps :

 export async function getServerSideProps({ req, query, res }) {

    console.log('in getServerSideProps');
    console.log(globalStore.get('baseUrl'));
    console.log(globalStore.get('baseUrl2'));
...
 

Ответ №2:

Я думаю, что в данном конкретном случае здесь можно использовать константы вместо реквизита.

Предлагаемое решение

В constants.js:

 export const BASE_URL = 'some url';
 

И на вашей странице:

 import * as Constants from '../path/to/constants';

export async function getServerSideProps({ req, query, res }) { 
  // use Constants.BASE_URL here

  return { props: { ..... } }
}
 

Почему реквизиты не будут работать так, как вы хотите?

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

  1. Запрос выполняется по маршруту.
  2. Next.js просматривает файл в pages/ поисках соответствующего маршрута
  3. Next.js будет запущен соответствующий метод на основе контекста выполнения (при рендеринге сервера, getServerSideProps)
  4. Next.js визуализирует компонент приложения, передавая ему pageProps, предоставленные из getServerSideProps
  5. Компонент приложения отображает компонент страницы

В этом случае вы создали парадокс. Подумайте о том, как поток реквизитов:

  1. Запускается getServerSideProps, возвращает объект pageProps
  2. Компонент приложения отображает, содержащий объект pageProps, переданный из getServerSideProps
  3. Компонент страницы отображает, передает pageProps

Если getServerSideProps отвечает за создание объекта pageProps, он также не может быть передан этому объекту в качестве аргумента.

Комментарии:

1. Спасибо за хорошее объяснение, но это динамическое значение. Существуют разные домены, которые указывают на одно и то же приложение NextJS. Я могу сделать это в каждом getServerSideProps (установить значение, но не получить), но лучше установить его один раз и использовать везде. Вы можете проверить мое решение, я не уверен, что оно лучшее.

2. Честно говоря, ваше решение выглядит неплохо, учитывая то, что вы пытаетесь сделать — кроме того, если я правильно понял, и вы обслуживаете одно приложение в нескольких доменах, я думаю, это также может помочь вам изменить объект запроса с помощью промежуточного программного обеспечения сервера, делая что-то вроде req.domain = 'whatever my domain is' , тогда вы сможете получить доступ к этому значению внутриваша getServerSideProps функция для различения контекста, в котором запущено приложение