我正在使用React
和Redux
构建一个通用应用,它通过NodeJS
和ExpressJS
在服务器端呈现。
一切正常,Express处理程序调用{{1}},每次都会创建{match} from 'react-router'
。
我遇到的问题是:new store instance
只呈现商店的{renderToString} from 'react-dom/server'
版本,如果商店更改某些商品(例如:通过{{调度的行动) 1}})商店将会更新,但pristine
在调用新的componentWillMount
之前不会更改。
generated markup
之前,我无法提供初始状态。renderToString
来电。这是我的示例代码:
renderToString
答案 0 :(得分:1)
一种方法是在Route组件上提供每路由操作作为静态方法,然后在调用renderToString
之前由您的快速中间件调用,例如。
class Index extends Component {
componentDidMount() {
// NOTE: The client fetches the data in `componentDidMount` instead of `componentWillMount` to ensure we don't duplicate efforts on the server.
const { dispatch } = this.props;
Index.fetchData({ dispatch });
}
render() {
...
}
}
Index.fetchData = function({ dispatch }) {
// Returns promise via redux-thunk / redux-promise
return dispatch(fetchDataIfNeeded());
};
export default connect(state => state)(Index);
然后在您的中间件中,您将在呈现之前调用匹配的路由组件上定义的所有静态fetchData
方法,例如
app.use((req, res) => {
match({
routes,
location: req.url
}, (error, redirectLocation, renderProps) => {
const store = configureStore();
const requests = renderProps.components
.map(component => {
// Handle `connect`ed components.
if (component.WrappedComponent) {
component = component.WrappedComponent;
}
if (component.fetchData) {
return component.fetchData({
dispatch: store.dispatch
})
.catch(() => {});
}
});
Promise.all(requests)
.then(() => {
// Store now contains all necessary state.
const markup = renderToString(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
);
res.send(`<!doctype html><html><body>${markup}</body></html>`);
});
});
});
您可以在60frames boilerplate中找到完整示例。
相关模块:
https://github.com/60frames/react-boilerplate/blob/master/src/components/index/Index.js
https://github.com/60frames/react-boilerplate/blob/master/src/server.js
答案 1 :(得分:1)
另一种找到的方法:
server-side
附加代码renderToString
示例:
import { END } from 'redux-saga';
store.runSaga = sagaMiddleware.run;
store.close = () => store.dispatch(END);
// server.js
store.runSaga(sagas).done.then(() => {
const state = store.getState();
const html = renderToString(rootComponent);
reply(renderApplication({state, html}));
});
renderToString(rootComponent);
store.close();