https://github.com/makeomatic/redux-prefetch
add layer, which handles state prefetching for universal apps built with react-router and redux
https://github.com/makeomatic/redux-prefetch
Last synced: 10 months ago
JSON representation
add layer, which handles state prefetching for universal apps built with react-router and redux
- Host: GitHub
- URL: https://github.com/makeomatic/redux-prefetch
- Owner: makeomatic
- License: mit
- Created: 2015-12-19T17:49:04.000Z (about 10 years ago)
- Default Branch: master
- Last Pushed: 2017-08-11T16:28:16.000Z (over 8 years ago)
- Last Synced: 2025-04-14T03:39:47.042Z (11 months ago)
- Language: JavaScript
- Size: 13.7 KB
- Stars: 15
- Watchers: 6
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Redux prefetch
Allows universal server-side rendering to be performed without much hassle.
Exposes `@fetch` decorator and `storeEnchancer`, which keeps track of unresolved promises.
Add `.resolve` function to store
## Install
`npm i redux-prefetch -S`
## Usage
The most important files are listed here, but look in the example for some extra stuff.
```js
// createStore.js
import { createStore, applyMiddleware, compose } from 'redux';
import promiseMiddleware from 'redux-promise-middleware';
import reducers from '../modules/reducers';
import { syncReduxAndRouter } from 'redux-simple-router';
import { canUseDOM as isBrowser } from 'fbjs/lib/ExecutionEnvironment';
import { reduxPrefetch } from 'redux-prefetch';
export default function returnStore(history, initialState) {
const middleware = [promiseMiddleware()];
let finalCreateStore;
if (isBrowser) {
finalCreateStore = applyMiddleware(...middleware);
} else {
finalCreateStore = compose(reduxPrefetch, applyMiddleware(...middleware));
}
const store = finalCreateStore(createStore)(reducers, initialState);
syncReduxAndRouter(history, store);
return store;
}
```
```js
// server.js
import React from 'react';
import merge from 'lodash/object/merge';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { match, RoutingContext } from 'react-router';
import routes from './routes';
import createStore from './store/create';
import metaState from './constants/config.js';
import HTML from './components/HTML';
import { Provider } from 'react-redux';
import serialize from 'serialize-javascript';
import DocumentMeta from 'react-document-meta';
export default function middleware(config = {}) {
const meta = merge({}, metaState, config);
// this is middleware for Restify, but can easily be changed for express or similar
return function serveRoute(req, res, next) {
match({ routes, location: req.url }, (err, redirectLocation, renderProps) => {
if (err) {
return next(err);
}
if (redirectLocation) {
res.setHeader('Location', redirectLocation.pathname + redirectLocation.search);
res.send(302);
return next(false);
}
if (!renderProps) {
return next('route');
}
// this is because we don't want to initialize another history store
// but apparently react-router passes (err, state) instead of (state), which
// is expected by redux-simple-router
const { history } = renderProps;
const { listen: _listen } = history;
history.listen = callback => {
return _listen.call(history, (_, nextState) => {
return callback(nextState.location);
});
};
const store = createStore(history, { meta });
// wait for the async state to resolve
store.resolve(renderProps.components, renderProps.params).then(() => {
const page = renderToString(
);
const state = store.getState();
const exposed = 'window.__APP_STATE__=' + serialize(state) + ';';
const html = renderToStaticMarkup(