私は自分の携帯電話からこれを入力していますので、私は、フォーマットの不足をお詫び申し上げます。
私のプロジェクトでは、あなたと似たようなことをしています。私は静的なfetchDataメソッドを持っている、私はrenderPropsからコンポーネントをループし、私は静的メソッドを呼び出して、約束を解決するのを待つ。
次に、私のreduxストアからget stateを呼び出し、文字列化して、クライアント上の初期状態オブジェクトをレンダリングできるようにサーバー上のレンダリング関数に渡します。
クライアントから、私はちょうどその初期状態変数を取得し、それを私のreduxストアに渡します。 Reduxはクライアントストアをサーバ上のものと一致するように処理します。そこから、あなたはあなたの店をプロバイダに渡し、いつものように続行するだけです。クライアント上で静的メソッドを呼び出す必要はありません。
私が言ったことの例として、コードが説明するように自分のgithubプロジェクトをチェックすることができます。 https://github.com/mr-antivirus/riur
お役に立てれば幸いです!
[編集]ここにコードがあります!
クライアント。JS
'use strict'
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { Router, browserHistory } from 'react-router';
import createStore from '../shared/store/createStore';
import routes from '../shared/routes';
const store = createStore(window.__app_data);
const history = browserHistory;
render (
<Provider store={store}>
<Router history={history} routes={routes} />
</Provider>,
document.getElementById('content')
)
Server.js
app.use((req, res, next) => {
match({ routes, location:req.url }, (err, redirectLocation, renderProps) => {
if (err) {
return res.status(500).send(err);
}
if (redirectLocation) {
return res.redirect(302, redirectLocation.pathname + redirectLocation.search);
}
if (!renderProps) {
return next();
}
// Create the redux store.
const store = createStore();
// Retrieve the promises from React Router components that have a fetchData method.
// We use this data to populate our store for server side rendering.
const fetchedData = renderProps.components
.filter(component => component.fetchData)
.map(component => component.fetchData(store, renderProps.params));
// Wait until ALL promises are successful before rendering.
Promise.all(fetchedData)
.then(() => {
const asset = {
javascript: {
main: '/js/bundle.js'
}
};
const appContent = renderToString(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
)
const isProd = process.env.NODE_ENV !== 'production' ? false : true;
res.send('<!doctype html>' + renderToStaticMarkup(<Html assets={asset} content={appContent} store={store} isProd={isProd} />));
})
.catch((err) => {
// TODO: Perform better error logging.
console.log(err);
});
});
});
RedditContainer.js
class Reddit extends Component {
// Used by the server, ONLY, to fetch data
static fetchData(store) {
const { selectedSubreddit } = store.getState();
return store.dispatch(fetchPosts(selectedSubreddit));
}
// This will be called once on the client
componentDidMount() {
const { dispatch, selectedSubreddit } = this.props;
dispatch(fetchPostsIfNeeded(selectedSubreddit));
}
... Other methods
};
HTML.js
'use strict';
import React, { Component, PropTypes } from 'react';
import ReactDom from 'react-dom';
import Helmet from 'react-helmet';
import serialize from 'serialize-javascript';
export default class Layout extends Component {
static propTypes = {
assets: PropTypes.object,
content: PropTypes.string,
store: PropTypes.object,
isProd: PropTypes.bool
}
render() {
const { assets, content, store, isProd } = this.props;
const head = Helmet.rewind();
const attrs = head.htmlAttributes.toComponent();
return (
<html {...attrs}>
<head>
{head.base.toComponent()}
{head.title.toComponent()}
{head.meta.toComponent()}
{head.link.toComponent()}
{head.script.toComponent()}
<link rel='shortcut icon' href='/favicon.ico' />
<meta name='viewport' content='width=device-width, initial-scale=1' />
</head>
<body>
<div id='content' dangerouslySetInnerHTML={{__html: content}} />
<script dangerouslySetInnerHTML={{__html: `window.__app_data=${serialize(store.getState())}; window.__isProduction=${isProd}`}} charSet='utf-8' />
<script src={assets.javascript.main} charSet='utf-8' />
</body>
</html>
);
}
};
繰り返しに...クライアントで
- は、状態変数を取得し、お店にそれを渡します。
- サーバーで、fetchDataを呼び出してストアを渡すコンポーネントをループします。約束が解決されるのを待ってからレンダリングしてください。
- HTML.js(あなたのrenderView関数)では、Reduxストアをシリアル化し、出力をクライアント用のjavascript変数にレンダリングします。
- あなたのリアクションコンポーネントでは、サーバーが呼び出すONLYの静的fetchDataメソッドを作成します。必要な措置を派遣します。
しかし、その方法を使用すると、私はサーバー側の約束を解決できないでしょうか? – kevinwolf