Далее. js: Сокращение выборки данных и обмен данными между страницами. - PullRequest
1 голос
/ 28 марта 2020

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

У меня проблема

Прямо сейчас у меня есть несколько страниц, все из которых содержат компонент, отображающий содержимое som stati c, и объект, содержащий некоторое динамическое содержимое c, извлекаемое из API. Каждая страница делает fetch() в своих getInitialProps(), чтобы получить свои собственные данные страницы, но также и данные нижнего колонтитула, , которые одинаковы для всех страниц .

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

Ответы, которые я ищу

Я не просто ищу решение этой одной проблемы, я Я ищу обзор, чтобы узнать некоторые новые практики для будущих проектов. Мне нравится писать «очевидный» код, поэтому я не ищу слишком хакерских решений, как, например, запись в объект window et c. Простые решения с меньшими зависимостями являются предпочтительными. Цель - быстрый сайт. Это не так важно, чтобы сократить использование сети / вызовы API.

То, что я до сих пор думал

Это возможные решения, которые я придумал, несколько от простого / очевидного до более сложный.

  1. Выполнение выборки внутри компонента Нижний колонтитул (на стороне клиента)
  2. Выполнение выборки в getInitialProps (на стороне сервера и на стороне клиента) для всех / страниц
  3. Выполнение получить в _app. js с HO C и подключить его к getInitialProps() и добавить его в реквизит, чтобы данные были доступны для всех страниц
  4. Используйте zeit / swr и предварительную выборку данных для кэширования данных
  5. Использование приставки для хранения глобального состояния

Все это «работает», но большинство из них будет без необходимости перезагружать данные и / или добавляет немного больше сложности. Вот плюсы / минусы, как я вижу (цифры те же, что и выше):

  1. ? Просто! Получить код только в одном месте, он находится там, где он используется. ? Данные извлекаются после загрузки страницы, поэтому содержимое «скачет» для просмотра. Данные обновляются постоянно.
  2. ? Просто! Данные извлекаются на сервер, поэтому содержимое доступно до отображения страницы. ? Данные обновляются для каждой страницы. Мы должны помнить, чтобы извлекать одинаковые данные нижнего колонтитула для каждой страницы в их getInitialProps().
  3. ? Мы можем сделать выборку в одном месте и добавить ее ко всем опорам страниц, чтобы данные нижнего колонтитула автоматически были доступны для реквизит всех страниц. Some Для некоторых может быть немного сложнее понять, что происходит, так как для этого требуется немного больше понимания того, как работает Next.js / React. Все еще обновляет данные для всех страниц. Теперь мы делаем два fetch() вызова друг за другом (сначала в _app. js для загрузки содержимого нижнего колонтитула, затем на каждой странице для получения пользовательского содержимого), так что это еще медленнее.
  4. what Довольно просто. Мы можем использовать предварительную выборку для загрузки данных в кэш даже до загрузки JS. После первой загрузки страницы у нас будет быстрый выбор данных. Может иметь код извлечения непосредственно в компоненте нижнего колонтитула. Technique Техника предварительной выборки rel="preload" не будет работать со всеми типами выборки (например, клиент Sanity, использующий groq). Чтобы не иметь «скачкообразного» содержимого, когда данные загружаются после начальной загрузки страницы, мы должны предоставить useSWR() с initialData, что все равно потребует от нас извлечения данных в getInitialProps(), но этого будет достаточно просто сделать это на на стороне сервера. Могли бы использовать новый getServerSideProps().
  5. ? Мы можем загрузить данные один раз (?) И сделать их доступными во всем приложении. Быстро и меньше / без повторной заправки. ? Добавляет внешнюю зависимость. Более сложным, так как вам придется учить лексему даже загружать один общий объект данных.

Текущее решение, использующее решение, описанное в пуле № 2.

const HomePage = (props) => {
  return (
    <Layout data={props.footer}>
       <Home data={props.page} />
    </Layout>
  )
}

// Not actual query, just sample
const query = `{
  "page": *[_type == "page"][0], 
  "footer": *[_type == "footer"][0]
}`

HomePage.getInitialProps = async () => {
  const data = await client.fetch(query)

  return {
    page: data.page
    footer: data.footer
  }
}

export default HomePage

Хотелось бы еще немного разобраться в этом. Я что-то упускаю очевидное?

1 Ответ

1 голос
/ 10 апреля 2020

O'right! Я нашел эту ветку, пока искал что-то еще. Но так как мне приходилось работать над подобными проблемами, я могу дать вам несколько указаний, и я сделаю все возможное, чтобы прояснить для вас.

Итак, есть некоторые данные, которыми вы хотите, чтобы они обменивались по всему Ваше приложение (страницы / компоненты).

  1. Далее. js использует компонент приложения для инициализации страниц. Вы можете переопределить его и контролировать инициализацию страницы. Для этого просто создайте файл _app.js в каталоге root из pages. Для получения дополнительной информации перейдите по этой ссылке: https://nextjs.org/docs/advanced-features/custom-app
  2. Так же, как вы можете использовать getInitialProps на своих страницах для извлечения данных из вашего API, вы также можете использовать тот же метод в _app.js. Итак, я бы выбрал те данные, которые мне нужны, чтобы поделиться ими со всем моим приложением и исключить вызовы API.

Что ж, теперь я могу придумать два способа обмена данными через мое приложение

  1. Использование createContext крючков.

1.1. Создайте DataContext, используя хуки createContext. и оберните <Component {...pageProps} /> своим <DataContext.Provider>. Вот фрагмент кода, чтобы дать вам лучшую подсказку:

<DataContext.Provider value={{ userData, footerData, etc... }}>
  <Component {...pageProps} />
</DataContext.Provider>

1.2. Теперь на других страницах / компонентах вы можете получить доступ к своему DataContext, как показано ниже:

const { footerData } = useContext(DataContext); 

И тогда вы сможете выполнять манипуляции в своем интерфейсе

заполняет props, используя getInitialProps

2.1. getInitialProps используется для асинхронной выборки некоторых данных, которые затем заполняют props. это было бы то же самое в _app.js.

Код в вашем _app.js будет выглядеть примерно так:

function MyApp({ Component, pageProps, footerData }) {
  //do other stuffs
  return (
   <Component {...pageProps} footerData={footerData} />
  ;
}

MyApp.getInitialProps = async ({ Component, ctx }) => {
  const footerRes = await fetch('http://API_URL');
  const footerData = await footerRes.json(); 
  let pageProps = {};
  if (Component.getInitialProps) {
    pageProps = await Component.getInitialProps(ctx);
  }
  return { pageProps, footerData };
};

2.2. Теперь на ваших страницах (не в ваших компонентах) вы можете получить доступ к реквизитам, включая те, которыми вы поделились с _app.js, и вы можете начать делать свои манипуляции.

Надеюсь, я смогу дать вам подсказку и направление. Веселитесь, исследуя.

...