Redux Hermit
is watch the dispatched promise actions for server-side-rending.
Installation
npm install redux-hermit --save
Problem
currently ReactDOMServer.renderToString
doesn't wait for the promise.
the following code will fail.
// Foo.jsx
import React from 'react';
import { connect } from 'react-redux';
export default connect(
state => state,
)(
class extends React.Component {
componentWillMount() {
if (this.props.alreadyInitialized) {
return;
}
// any asynchronous processing...
console.log('mount props:', this.props);
this.props.dispatch(new Promise((resolve) => {
setTimeout(() => {
resolve({
type: 'update',
payload: {
foo: 'complete',
},
});
}, Math.random() * 500);
}));
}
render() {
return (
<div>
{this.props.foo || 'loading...'}
{this.props.children}
</div>
);
}
}
);
// index.jsx
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise';
import { Provider } from 'react-redux';
import Foo from './Foo';
const store = createStore(
(state = {}, action) => {
if (action.type === 'alreadyInitialized') {
return Object.assign({}, state, { alreadyInitialized: true });
}
if (action.type === 'update') {
return Object.assign({}, state, action.payload);
}
return state;
},
applyMiddleware(
promiseMiddleware,
),
);
const provider = (
<Provider store={store}>
<Foo />
</Provider>
);
console.log('state:', store.getState())
console.log(renderToStaticMarkup(provider));
babel-node index.jsx
# state: {}
# mount props: { dispatch: [Function] }
# <div>loading...</div>
promiseWatchMiddleware.wait
is wait the fulfill of captured promise actions at componentWillMount.
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise';
import createPromiseWatchMiddleware from 'redux-hermit';
import { Provider } from 'react-redux';
import Foo from './Foo';
const promiseWatchMiddleware = createPromiseWatchMiddleware();
const store = createStore(
(state = {}, action) => {
if (action.type === 'alreadyInitialized') {
return Object.assign({}, state, { alreadyInitialized: true });
}
if (action.type === 'update') {
return Object.assign({}, state, action.payload);
}
return state;
},
applyMiddleware(
promiseWatchMiddleware,
promiseMiddleware,
),
);
const provider = (
<Provider store={store}>
<Foo />
</Provider>
);
renderToStaticMarkup(provider);
promiseWatchMiddleware.wait().then(() => {
store.dispatch({ type: 'alreadyInitialized' });
console.log('state:', store.getState());
console.log(renderToStaticMarkup(provider));
});
you can server-side-rendering.
babel-node index.jsx
# state: { foo: 'complete' }
# <div>complete</div>
Attention
- that you must run the twice render.
- that also
componentWillMount
is performed twice(can interrupted by using thealreadyInitialized
).
Development
Requirement global
- NodeJS v5.7.0
- Npm v3.7.1
git clone https://github.com/59naga/redux-hermit
cd redux-hermit
npm install
npm test