在 NextJS 的 getServerSideProps 中访问 Redux 存储

Posted

技术标签:

【中文标题】在 NextJS 的 getServerSideProps 中访问 Redux 存储【英文标题】:Access Redux store in getServerSideProps in NextJS 【发布时间】:2020-10-30 05:53:22 【问题描述】:

我想在 getServerSideProps() 中访问我的 redux 存储;在我的 Next.js 应用程序中。我想拥有存储在 Redux Store 中的用户 ID,以便我可以预加载用户数据。我现在正在使用 next-redux-wrapper 并且在客户端它正在工作。但是当我在 getServerSideProps() 中访问我的商店时,它会返回初始状态。我检查了几个示例,但无法正常工作。

我的 configureStore.js

import  createStore, applyMiddleware, compose  from "redux";
import reducer from "./../service";
import thunk from 'redux-thunk'
import  createWrapper, HYDRATE from 'next-redux-wrapper';

const SET_CLIENT_STATE = 'SET_CLIENT_STATE';

const storeEnhancers = typeof window != 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

const makeStore = ( isServer ) => 

  if (isServer) 

    return createStore(reducer, storeEnhancers(applyMiddleware(thunk)) );

   else 

      const  persistStore, persistReducer  = require('redux-persist');
      const storage = require('redux-persist/lib/storage').default;

      const persistConfig = 
          key: 'nextjs',
          whitelist: ['userReducer'],
          storage
      ;

      const store = createStore(
        persistReducer(persistConfig, reducer),
        storeEnhancers(applyMiddleware(thunk))
      );
  
      store.__PERSISTOR = persistStore(store);

      return store;
  
;

export const wrapper = createWrapper(makeStore);

export const setClientState = (clientState) => (
  type: SET_CLIENT_STATE,
  payload: clientState
);

我的 _app.js:

import React from 'react';
import PropTypes from 'prop-types';
import Head from 'next/head';
import  ThemeProvider  from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import theme from '../styles/theme';
import  useStore  from "react-redux";
import  PersistGate  from 'redux-persist/integration/react';
import wrapper from './../redux/configureStore';

const MyApp = (Component, pageProps) => 
  const store = useStore((state) => state);

  React.useEffect(() => 
    const jssStyles = document.querySelector('#jss-server-side');
    if (jssStyles) 
      jssStyles.parentElement.removeChild(jssStyles);
    
  , []);

  return (
    <React.Fragment>
      <Head>
        <title>Deeltuinen</title>
        <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
      </Head>
        <PersistGate persistor=store.__PERSISTOR loading=null>
          <ThemeProvider theme=theme>
            <CssBaseline />
            <Component ...pageProps />
          </ThemeProvider>
        </PersistGate>
    </React.Fragment>
  );


export default wrapper.withRedux(MyApp);

MyApp.propTypes = 
  Component: PropTypes.elementType.isRequired,
  pageProps: PropTypes.object.isRequired
;

最后是我想要获取商店状态的页面:

import React from 'react';
import Layout from './../../components/Layout';
import API from './../../service/api';
import connect from "react-redux";
import wrapper, setClientState from './../../redux/configureStore';

const AccountSettings = (data) => 
 
  return (
    <Layout title="Deeltuinen">
      // User form
    </Layout>
  );


export const getServerSideProps = wrapper.getServerSideProps(
  (store, req, res) => 
    const state = store.getState();
    console.log(state);

    //const data = await API.getUser(state.userReducer.user.token);
  
);

export default connect(state => state,setClientState)(AccountSettings);

【问题讨论】:

getServerSideProps 几乎是在页面被点击时运行的前几个函数之一,那么它如何包含除 redux 的 intialState 之外的任何其他状态? 我正在使用 redux persist 来保存页面之间的存储。我将用户 ID 存储在我想在 getServerSideProps 中使用的 Redux 存储中。 Redux persist 默认将 redux 状态存储在 localStorage 中,这是一种浏览器实现,因此在服务器端不可用。除非你手动实现了一些东西来持久化状态服务器端,否则它不会工作。 那么获取用户 ID 并使用用户数据创建服务器端呈现页面的最佳策略是什么? 【参考方案1】:

我的代码:

export const getServerSideProps = wrapper.getServerSideProps(async ( req, res, store ) => 
  const state = store.getState();
  console.log('state', state);

  return 
    props: ,
  ;
);
`

【讨论】:

我得到了初始存储状态,没有我之前存储的值。 @Emke 你找到解决方案了吗?【参考方案2】:

如果您需要将一些参数传递给 getServerSideProps,您应该设置页面结构来执行此操作。

例子:

如果我需要从用户那里获得一些积分,而我的 api 需要“userId”参数,我会这样设置我的页面:

pages/credits/[userId].js

这样我可以通过这种方式访问​​getServerSideProps函数中的userId参数:

export async function getServerSideProps (context) 

   const  userId  = context.params
   
   ...
   // API call to get the Credits by userId

【讨论】:

以上是关于在 NextJS 的 getServerSideProps 中访问 Redux 存储的主要内容,如果未能解决你的问题,请参考以下文章

如何在 nextjs 中添加活动的 className

从零搭建一个基于React+Nextjs的SSR网站:如何搭建服务器并部署Nextjs项目

NextJS:TailwindCSS 无法在生产环境中工作

nextjs - 在开发模式下使用 _error.js

无法在 NextJs + Storybook 中提供静态文件

NextJs App 在 Azure Web App 中部署时未在 nextjs 公用文件夹中加载图像