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

Как лучше организовать взаимодействие между компонентами с использованием Next.JS и серверных компонентов, учитывая SSR? Например, у меня есть структура:

```jsx
<Things>
   <ThingsList/>
   <ThingDetails/>
<Things/>
```

В `ThingsList` у меня есть список "штучек", и при выборе одной из них в `ThingDetails` отображается их содержимое для просмотра и редактирования. В обычном React я бы вынес состояния в компоненте `Things` и перехватил бы базовую загрузку данных из базы данных, а затем передал бы ID выбранной "штучки" и другую необходимую информацию через пропсы.

```jsx
<Things>
   <ThingsList items={things} onSelect={setSelectedThingID}/>
   <ThingDetails item={things.get(selectedThingID} onSubmit={onThingDetailsSubmit}/>
<Things/>
```

Однако в Next серверные компоненты не могут использовать хуки и должны быть stateless. Записывать `useClient` повсюду означает, фактически, отказаться от преимуществ Next.JS. Я не понимаю, как это сделать без этого (потому что я малоопытный :)).

Какая считается наилучшей практикой в таких случаях? Как правильно организовать загрузку и передачу данных в этом контексте?
  • 28 октября 2023 г. 21:10
Ответы на вопрос 2
В Next.js есть несколько способов сохранить состояние и загрузить данные.

1. Сохранение состояния на сервере: Вы можете использовать серверный кэш, такой как Redis или Memcached, чтобы сохранить состояние между запросами. Вы можете использовать `getServerSideProps` в Next.js для загрузки данных из кэша и передачи их в компоненты через пропсы.

```jsx
export async function getServerSideProps() {
   // Загрузка данных из кэша
   const data = await cache.get('data');

   return {
      props: {
         data
      }
   }
}
```

2. Сохранение состояния на клиенте: Вы можете использовать состояние компонентов вместе с `useEffect` и `useState` для сохранения состояния на клиенте. Вы можете загрузить данные с помощью Ajax или другого метода и сохранить их в состоянии.

```jsx
export default function Things() {
   const [data, setData] = useState([]);

   useEffect(() => {
      // Загрузка данных
      fetchData().then((response) => {
         setData(response.data);
      });
   }, []);

   return (
      <>
         <ThingsList items={data} onSelect={setSelectedThingID} />
         <ThingDetails item={findSelectedThing(data, selectedThingID)} onSubmit={onThingDetailsSubmit} />
      </>
   );
}
```

3. Использование серверных компонентов: В более новых версиях Next.js появились серверные компоненты, которые предоставляют возможность организовать хранение состояния на сервере без применения хуков. Вы можете использовать `getServerSideProps` для загрузки данных и передачи их в серверные компоненты.

```jsx
export async function getServerSideProps() {
   // Загрузка данных
   const response = await fetchData();

   return {
      props: {
         data: response.data
      }
   }
}

export default function Things({ data }) {
   return (
      <>
         <ThingsList items={data} onSelect={setSelectedThingID} />
         <ThingDetails item={findSelectedThing(data, selectedThingID)} onSubmit={onThingDetailsSubmit} />
      </>
   );
}
```

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

```jsx
<Things>
   <ThingsList items={data} onSelect={setSelectedThingID} />
   <ThingDetails item={findSelectedThing(data, selectedThingID)} onSubmit={onThingDetailsSubmit} />
</Things>
```

Общая практика состоит в том, чтобы организовывать серверные запросы и загрузку данных в верхнеуровневых компонентах и передавать данные с помощью пропсов или контекста на более низкоуровневые компоненты.
1. Можно использовать состояние общего доступа, такое как Redux.
2. Можно использовать контекст.
3. Можно изменять URL и извлекать выбранный деталь из параметра.
4. Можно разместить элементы на отдельных страницах.

Лично я предпочитаю использовать четвертый вариант. Он проще и логичнее. При обновлении страницы просмотр выбранного элемента не сбрасывается. То же самое можно сказать и о третьем варианте.

Одна из плюсов четвертого варианта заключается в том, что вы разделяете свой код на отдельные блоки. При сборке вашего кода бандлы будут иметь меньший объем. Если же вы размещаете все на одной странице, это приведет к созданию одного большого файла.

Чтобы использовать хуки и колбэки в Next.js 13, вам просто нужно вынести часть кода, в которой используются хуки, в отдельный компонент и пометить его как "useClient". Это позволит выполнять весь код на сервере, за исключением небольшого фрагмента, который будет выполняться на клиенте. Например, я выношу только кнопку, по которой нужно осуществить подписку при клике. Все остальное будет выполняться на сервере.
Похожие вопросы