Как инициализировать хранилище из данных ssr?

Я работаю над проектом Next.js, организованным в каталоги, а также реализую Redux для управления состоянием на стороне клиента. У меня есть страницы, расположенные в каталоге приложения t.

Кроме того, я получаю некоторые данные на стороне сервера и хочу инициализировать свое хранилище Redux с помощью этих данных, отображаемых на стороне сервера.

Вот пример того, как я получаю данные в компоненте домашней страницы:

Home.tsx

import { Box, Button, Typography } from "@mui/material";
import blogsecure from "./services/blogSecure";
import { BlogGetData } from "./models/BlogGet";

export const fetchData = async () => {
  const response = await blogsecure.get('/blogs/fetch_all'); //<- I want to initalize from this data

  if (response.status !== 200) {
    throw new Error("Failed to fetch API data");
  }
  return response.data;
};

const Home = async() => {
  const blogs: BlogGetData[] = await fetchData();
  return (
    <Box sx = {{ position: 'relative', height: '100%' }}>
      <Button sx = {{ position: 'absolute', bottom: 16, right: 16 }}>
        Create blog
      </Button>
      {blogs.map((blog) => <Typography>{blog.title}</Typography>)}
    </Box>
  );
}

export default Home;

Вот как я обрабатываю инициализацию Redux в своих файлах StoreProvider.tsx и store.ts:

StoreProvider.tsx

import { useRef } from 'react';
import { Provider } from 'react-redux';
import { AppStore, makeStore } from '../lib/store';

const StoreProvider = ({ children }: { children: React.ReactNode }) => {
  const storeRef = useRef<AppStore>();
  if (!storeRef.current) {
    storeRef.current = makeStore();
  }

  return <Provider store = {storeRef.current}>{children}</Provider>;
};

export default StoreProvider;

store.ts

import { configureStore } from '@reduxjs/toolkit';
import authReducer from './feature/auth/authSlice';
import blogsReducer from './feature/blogs/blogFetchSlice';
import userReducer from './feature/user/userSlice';

export const makeStore = () => {
  return configureStore({
    reducer: {
      auth: authReducer,
      user: userReducer,
      blogs: blogsReducer,
    }
  });
}

export type AppStore = ReturnType<typeof makeStore>;
export type RootState = ReturnType<AppStore['getState']>;
export type AppDispatch = AppStore['dispatch'];

В моем срезе Redux для загрузки блогов (blogFetchSlice.tsx) я определяю начальное состояние и редукторы следующим образом:

блогFetchSlice.tsx

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { BlogFetchAllState } from './types'; // Assuming you have defined types for state

export const fetchAllBlogs = createAsyncThunk(
  // my async logic here
);

const initialState: BlogFetchAllState = {
  blogs: null,<-- If I initialize here it is done from client side
  loading: false,
  error: null,
  current_blog: null
};

const blogFetchSlice = createSlice({
  name: 'blogFetchAll',
  initialState,
  reducers: {
    // Additional reducers if needed
  },
  extraReducers: (builder) => {
    // slice actions
  }
});

export default blogFetchSlice.reducer;

This setup initializes the Redux store with the server-side rendered data and provides a structure for managing your client-side state with Redux. If you need further assistance or clarification, feel free to ask!

I'm structuring a Next.js project with Redux for client-side state management. Each page resides in the app directory for better organization. I need guidance on initializing the Redux store with data fetched on the server side. Can you help me set up Redux initialization from server-side rendered data in this Next.js project?

65
1

Ответ:

Решено

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

React потребуется добавить несколько примитивов для ввода данных в поток, прежде чем это станет возможным с помощью Redux.