私はReact、React-router、Redux、ImmutableでUniversal/Isomorphicアプリを構築しようとしています。私は、サーバーのレンダリングを行い、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;
}
減速コード:
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ファイルのコードがまったく実行されていなかったと思います。
更新日:減速で "HANDLE_CLICK" を扱うしようとしたときにエラーを引き起こすコード: 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);
なぜ 'createStore'の後に' 'SET_STATE''をディスパッチしていますか? – DDS
ありがとうございます。クライアントコードとサーバーコードの両方でディスパッチを削除しました。まだ動かない。何か案が? –