#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 это похоже на это:
- Запрос выполняется по маршруту.
- Next.js просматривает файл в
pages/
поисках соответствующего маршрута - Next.js будет запущен соответствующий метод на основе контекста выполнения (при рендеринге сервера, getServerSideProps)
- Next.js визуализирует компонент приложения, передавая ему pageProps, предоставленные из getServerSideProps
- Компонент приложения отображает компонент страницы
В этом случае вы создали парадокс. Подумайте о том, как поток реквизитов:
- Запускается getServerSideProps, возвращает объект pageProps
- Компонент приложения отображает, содержащий объект pageProps, переданный из getServerSideProps
- Компонент страницы отображает, передает pageProps
Если getServerSideProps отвечает за создание объекта pageProps, он также не может быть передан этому объекту в качестве аргумента.
Комментарии:
1. Спасибо за хорошее объяснение, но это динамическое значение. Существуют разные домены, которые указывают на одно и то же приложение NextJS. Я могу сделать это в каждом
getServerSideProps
(установить значение, но не получить), но лучше установить его один раз и использовать везде. Вы можете проверить мое решение, я не уверен, что оно лучшее.2. Честно говоря, ваше решение выглядит неплохо, учитывая то, что вы пытаетесь сделать — кроме того, если я правильно понял, и вы обслуживаете одно приложение в нескольких доменах, я думаю, это также может помочь вам изменить объект запроса с помощью промежуточного программного обеспечения сервера, делая что-то вроде
req.domain = 'whatever my domain is'
, тогда вы сможете получить доступ к этому значению внутривашаgetServerSideProps
функция для различения контекста, в котором запущено приложение