客户端无法呈现初始状态

时间:2016-09-11 02:38:51

标签: reactjs redux react-redux immutable.js react-router-redux

我正在尝试使用React,React-router,Redux和Immutable构建通用/同构应用程序。我设法使服务器渲染并向客户端发送初始状态和HTML。但客户端似乎根本不会使用该初始状态。

我的服务器代码:

1.Handle路线:

import {match,RouterContext,Router,Route,browserHistory} from "react-router";
import {Provider} from "react-redux";
import {createStore} from "redux";
import {createRouter} from "../../shared/support/routers";
import reducer from "../../shared/reducer";
import ReactDOMServer  from "react-dom/server";
import React from "react";
import Immutable from "immutable";
import {RenderPage} from "../routes/helper";

function homeRender(req, res) {

    match({routes, location: req.url}, (err, redirectLocation, renderProps)=> {
        if (redirectLocation) {
            //@TODO: response redirect location
            console.log('redirect location');
        }
        if (err) {
            //@TODO: response error
            console.log(err.stack);
        }
        if (!renderProps) {
            //@TODO: route to 404
            console.log("no renderProps");
        }

        Article.getArtilceByPage(1,20)
            .then(questions=>{
                let state = Immutable.fromJS({
                    title:"Home page render on server side",
                    qs:questions
                });
                let store = createStore(reducer,state);
                store.dispatch({
                    type: "SET_STATE",
                    state: state
                });
                let html = ReactDOMServer.renderToString(
                    <Provider store={store}>
                        <RouterContext {...renderProps}/>
                    </Provider>
                );
                let fullPage = RenderPage(html, store.getState());
                res.end(fullPage);
            })
        .catch(function(e) {
            res.end(e);
        });

    });
}

2。呈现页面代码:window.__PRELOADED_STATE__呈现在响应的HTML

export function RenderPage(content,state) {
    let temp = `<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
    <title>${state.get('title')}</title>
    <meta name='og:title' content='Dont ask me for it'/>
    <script>
          window.__PRELOADED_STATE__ = ${JSON.stringify(state)}
    </script>
  </head>
  <body>
    <div id='app'><div>${content}</div></div>
     <script type="text/javascript" src="manifest.js"></script>
    <script type="text/javascript" src="vendor.js"></script>
     <script type="text/javascript" src="app.js"></script>



  </body>
  </html>`;
    return temp;
}

reducer code:

import {Map} from "immutable";
export default function (state = Map(), action) {
    switch (action.type) {
        case "SET_STATE":
            return setState(state,action.state);
        case "HANDLE_CLICK":
            handleClick();
            //console.log("Hello there");
    }
}
//initial state
function setState(state,newState) {
    return state.merge(newState);
}
//handle user click
function handleClick(state,action) {

    console.log("This one could not be pass child comps");

}

共享代码以在客户端和服务器上创建路由:

import {Router,Route} from "react-router";
import React from "react";
import App from "../components/app";
import {HomeContainer} from "../components/home";
import {TagContainer} from "../components/tag";

export function createRouter(hist) {
    const routes = <Route component={App}>
        <Route path="/" component={HomeContainer}/>
        <Route path="tag" name="tag" component={TagContainer}/>
    </Route>;
    return (
        <Router history={hist}>{routes}</Router>
    );
}

最后:客户端代码:

import React from "react";
import ReactDOM from "react-dom";
import {Router,Route,browserHistory } from "react-router";
import {Provider} from "react-redux";
import {createStore} from "redux";
import reducer from "./reducer";
import Immutable from "immutable";
import {createRouter} from "./support/routers";

console.log(windows.__PRELOADED_STATE__);
const state = Immutable.fromJS(window.__PRELOADED_STATE__);
const store = createStore(reducer,state);
const routes = createRouter(browserHistory);


store.dispatch({
    type: "SET_STATE",
    state: state
});
    ReactDOM.render(
        <Provider store={store}>
            {routes}
        </Provider>
        , document.getElementById("app"));

结果:客户端可以查看服务器呈现的HTML。但它不能从窗口初始存储/状态。 PRELOADED_STATE 。 我怀疑index.js文件中的代码根本没有运行。

更新:尝试处理&#34; HANDLE_CLICK&#34;时导致错误的代码在reducer中: home.js

import React from "react";
import PureRenderMixin from 'react-addons-pure-render-mixin';
import {connect} from "react-redux";
import * as actionCreator from "./support/action_creator";
import HomeList from "./subComponents/homelist";

export class HomeComp extends React.Component {
    constructor(props) {
        super(props);
        this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
    }

    getQuestions() {
        return this.props.data.questions || [];
    }

    render() {
        //console.log(this.getQuestions());
        //console.log(this.props.questions);
        //console.log(this.props);
        return <div className="home">
            <h1>kkk</h1>
            <smal>Here is a list for home stuff</smal>
            <HomeList {...this.props}/>
        </div>
    }
}
//<HomeList {...this.props}/>
function mapStateToProps(state) {
    return {
        questions: state.get('qs') // this cause error in console devTool
    };
}
export const HomeContainer = connect(mapStateToProps, actionCreator)(HomeComp);

enter image description here

1 个答案:

答案 0 :(得分:0)

当你console.log状态时,你将从windows抓住它并且不存在并且应该扔掉。

因为throw会破坏代码流,所以它永远不会进入render调用。

您应该始终使用DevTools来调试您的问题。编码盲目非常困难。知道为什么你的应用程序纯粹基于它产生的输出工作是非常困难的。

使用调试工具,您可以检查变量,设置断点和评估特殊代码。这真的是不可或缺的。