我正在尝试使用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);
答案 0 :(得分:0)
当你console.log
状态时,你将从windows
抓住它并且不存在并且应该扔掉。
因为throw会破坏代码流,所以它永远不会进入render
调用。
您应该始终使用DevTools来调试您的问题。编码盲目非常困难。知道为什么你的应用程序纯粹基于它产生的输出工作是非常困难的。
使用调试工具,您可以检查变量,设置断点和评估特殊代码。这真的是不可或缺的。