2017-09-02 257 views
0

我正在尝试将redux集成添加到我的Next.js应用程序,但我无法获得serverside渲染的工作方式应该。我基于我的执行关闭the official nextjs redux example。最后,当页面从服务器返回时,数据在输出中显示为JSON数据,但基于此数据的实际渲染没有发生。奇怪的是在我使用过redux之前,内容DID呈现的方式应该是Next.js + Redux服务器端渲染:有数据,但不在服务器端渲染

当然,我也得到了React的校验和警告,表明服务器上的标记是不同的。

我不知道如何在服务器端正常工作。有什么我失踪了吗?

这是一个被Next.js生成的HTML:

<h1 data-reactid="3">Test page</h1> 

</div></div></div><div id="__next-error"></div></div><div><script> 
      __NEXT_DATA__ = {"props":{"isServer":true,"store":{}, 

"initialState":{"authors":{"loading":false,"items":{"4nRpnr66B2CcQ4wsY04CIQ":… } 

,"initialProps":{}},"pathname":"/test","query":{},"buildId":1504364251326,"buildStats":null,"assetPrefix":"","nextExport":false,"err":null,"chunks":[]} 
      module={} 
      __NEXT_LOADED_PAGES__ = [] 
      __NEXT_LOADED_CHUNKS__ = [] 

      __NEXT_REGISTER_PAGE = function (route, fn) { 
      __NEXT_LOADED_PAGES__.push({ route: route, fn: fn }) 
      } 

      __NEXT_REGISTER_CHUNK = function (chunkName, fn) { 
      __NEXT_LOADED_CHUNKS__.push({ chunkName: chunkName, fn: fn }) 
      } 
     </script><script async="" id="__NEXT_PAGE__/test" type="text/javascript" src="/_next/1504364251326/page/test"></script><script async="" id="__NEXT_PAGE__/_error" type="text/javascript" src="/_next/1504364251326/page/_error/index.js"></script><div></div><script type="text/javascript" src="/_next/1504364251326/manifest.js"></script><script type="text/javascript" src="/_next/1504364251326/commons.js"></script><script type="text/javascript" src="/_next/1504364251326/main.js"></script></div></body></html> 

正如你可以看到,initialState值填充,它包含了所有需要的数据,但DOM仍显示为空!

如果我在客户端渲染dom,js将拾取初始内容并将已加载的内容重新放入页面。

这里是我的测试页面的JS文件:

import React from 'react' 
import map from 'lodash.map'; 
import { initStore } from '../lib/store'; 
import * as actions from '../lib/actions'; 
import withRedux from 'next-redux-wrapper'; 

class IndexPage extends React.PureComponent { 
    static getInitialProps = ({ store, req }) => Promise.all([ 
    store.dispatch(actions.fetchAll) 
    ]).then(() => ({})) 

    render() { 
    const latestPlants = this.props.plants.latest || []; 

    return (
     <div> 
     <h1>Test page</h1> 
     { map(this.props.plants.items, p => (
      <div>{p.fields.name}</div> 
     ))} 
     </div> 
    ) 
    } 
} 

export default withRedux(initStore, data => data, null)(IndexPage) 

不管它的价值,这里就是我上面所说的动作:

export const fetchAll = dispatch => { 
    dispatch({ 
    type: LOADING_ALL 
    }) 

    return axios.get('/api/frontpage') 
    .then(response => { 
     const data = response.data 
     dispatch({ 
     type: RESET_AUTHORS, 
     payload: data.authors 
     }) 
     dispatch({ 
     type: RESET_PLANTS, 
     payload: data.plants 
     }) 
     dispatch({ 
     type: RESET_POSTS, 
     payload: data.posts 
     }) 
    }); 
} 

任何帮助,这将不胜感激,我不知如何按预期完成这项工作。任何人有任何线索?如果有什么我可以澄清的话,也请发表评论。

+0

我意识到使用Immutable.js,该问题与我在我的商店,但我还没有准确地找到故障原因导致问题 – Marco

回答

0

我建议在不同部位分割的代码。首先我将创建一个店,像这样的东西:

import { createStore, applyMiddleware } from 'redux'; 
import thunkMiddleware from 'redux-thunk'; 
import reducer from './reducers' 

export const initStore = (initialState = {}) => { 
    return createStore(reducer, initialState, applyMiddleware(thunkMiddleware)) 
} 

然后,我将创建同类型的店来处理:

常数初始化状态= { 作者:空, 植物:空, 帖子:空 }

export default (state = initialState, action) => { 
    switch (action.type) { 
    case 'RESET': 
     return Object.assign({}, state, { 
     authors: action.authors, 
     plants: action.plants, 
     posts: action.posts 
     }) 
    default: 
     return state 
    } 
} 

在行动我有这样的事情:

export const fetchAll = dispatch => { 
    return axios.get('/api/frontpage') 
    .then(response => { 
     const data = response.data 
     dispatch({ 
     type: 'RESET', 
     authors: data.authors, 
     plants: data.plants, 
     posts: data.posts 
     }) 
    }); 
} 

指数将是这样的:

import React from 'react' 
import { initStore } from '../store' 
import withRedux from 'next-redux-wrapper' 
import Main from '../components' 

class Example extends React.Component { 
    render() { 
    return (
     <div> 
     <Main /> 
     </div> 
    ) 
    } 
} 

export default withRedux(initStore, null)(Example) 

和组件主营:

import React, {Component} from 'react' 
import { connect } from 'react-redux' 
import { bindActionCreators } from 'redux' 
import { fetchAll } from '../../actions' 

class Data extends Component { 
    componentWillMount() { 
    this.props.fetchAll() 
    } 

    render() { 
    const { state } = this.props 
    return (
     <div> 
     <h1>Test page</h1> 
     { map(state.plants.items, p => (
      <div>{p.fields.name}</div> 
     ))} 
     </div> 
    ) 
    } 
} 

const mapStateToProps = (state) => { 
    return { 
    state 
    } 
} 

const mapDistpatchToProps = dispatch => { 
    return { 
    fetchAll: bindActionCreators(fetchAll, dispatch) 
    } 
} 

export default connect(mapStateToProps, mapDistpatchToProps)(Data) 

做出改变你需要什么。

您可以检查一些例子全在这里:
Form handler
Server Auth