Next.js + Redux:在 getInitialProps 中获取数据操作完成之前加载一个页面

Posted

技术标签:

【中文标题】Next.js + Redux:在 getInitialProps 中获取数据操作完成之前加载一个页面【英文标题】:Next.js + Redux: A Page is loaded before fetching data actions in getInitialProps is complete 【发布时间】:2020-08-11 08:28:25 【问题描述】:

我正在尝试通过在页面中触发 getInitialProps 中的“getItems”操作从 API 获取数据。(假设它是页面 A)

如果我通过Link(next/link)从其他页面转到页面A,则可以成功获取数据。

但是,如果我在页面 A 中刷新,则永远不会获取数据,我必须通过触发 getItems 操作手动获取数据。

任何人都可以告诉我即使在刷新页面时我应该如何获取数据?

_app.js

const MyApp = props => 
  const  Component, pageProps, store  = props

  return (
    <>
      <Head>
        <link rel='stylesheet' href='/styles/global.css' />
      </Head>
      <Provider store=store>
        <MainLayout>
          <Component ...pageProps />
        </MainLayout>
      </Provider>
    </>
  )


MyApp.getInitialProps = async ( Component, ctx ) => 
  const pageProps = Component.getInitialProps
    ? await Component.getInitialProps(ctx)
    : 
  return  pageProps 


export default withRedux(store)(MyApp)

pageA.js

import Head from 'next/head'
import Link from 'next/link'
import  connect  from 'react-redux'
import  getItems, addItem  from '../../store/actions/itemAction'
import  GET_ITEMS  from '../../store/types'

const Index = props => 
  return (
    <>
      <Head>
        <title>Item List</title>
        <link rel='stylesheet' href='/styles/css_pages/shop.css' />
      </Head>
      <div><div>
    </>
  )


Index.getInitialProps = async ( store ) => 
  await store.dispatch(getItems())
  return 


const mapStateToProps = state => (
  goods: state.item.goods,
)

const mapDispatchToProps = dispatch => (
  getItems: () => dispatch(getItems()),
  addItem: () => dispatch(addItem()),
)

export default connect(mapStateToProps, mapDispatchToProps)(Index)

itemAction.js

import fetch from 'isomorphic-unfetch'
import  GET_ITEMS  from '../types'

export const getItems = () => 
  return dispatch => 
    fetch('http://localhost:5000/item')
      .then(res => res.json())
      .then(data => dispatch( type: GET_ITEMS, payload: data ))
      .catch(err => console.error(err))
  

itemReducer.js

import  GET_ITEMS  from '../types'

const initialState =  goods: [], loading: false 

const itemReducer = (state = initialState, action) => 
  switch (action.type) 
    case GET_ITEMS:
      return 
        ...state,
        goods: action.payload,
        loading: false,
      

    default:
      return state
  


export default itemReducer

store.js

import  createStore, applyMiddleware  from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './rootReducer'

const bindMiddleware = middleware => 
  if (process.env.NODE_ENV !== 'production') 
    const  composeWithDevTools  = require('redux-devtools-extension')
    return composeWithDevTools(applyMiddleware(...middleware))
  

  return applyMiddleware(...middleware)


export const store = () => createStore(rootReducer, bindMiddleware([thunk]))

rootReducer.js

import  combineReducers  from 'redux'
import itemReducer from './reducers/itemReducer'

const rootReducer = combineReducers(
  item: itemReducer
)

export default rootReducer

【问题讨论】:

【参考方案1】:

在返回和呈现之前,您应该等待 pageA 的 getInitialProps 中的 getItems 操作响应。

我想如果你尝试使用await,它会解决你的问题:

Index.getInitialProps = async ( store ) => 
  await store.dispatch(getItems())
  return 

【讨论】:

我试过了,但同样的事情发生了。刷新时永远不会获取数据。 只是为了确定,您如何检查是否使用此代码获取数据? 刷新后控制台记录道具时,“props.goods”数组为空,这意味着我猜数据永远不会被获取。但是,当通过 Link(next/link) 呈现客户端时,它不是空的,而是来自 DB 的数据。【参考方案2】:

我会尝试研究这个例子https://github.com/vercel/next.js/blob/canary/examples/with-redux-wrapper/store/store.js

建议使用next-redux-wrapper 包来包装您的页面。然后您将在您的Index.getInitialProps 上获得store 对象

【讨论】:

以上是关于Next.js + Redux:在 getInitialProps 中获取数据操作完成之前加载一个页面的主要内容,如果未能解决你的问题,请参考以下文章

Next.js:在 getServerSideProps 中使用带有 TypeScript 的 next-redux-wrapper 调用 Thunks?

将 react redux 与 next.js 一起使用

我已经在 next js 中使用 next-redux-wrapper 成功实现了 redux-persist

redux 如何与 next.js 一起工作?

Next.js + Redux:在服务器端获取的数据永远不会移动到页面道具

Next.js+Redux 认证和重定向