fetch-component-data
Advanced tools
Comparing version 0.3.2 to 5.0.0
@@ -0,4 +1,4 @@ | ||
## [0.5.0] | ||
- Update to use `react-router` v4 and `react-router-redux`. No longer supports `redux-router`. `fechComponentDataMiddleware` is now a function that must be called with a `getRoutes` param to create the middleware, see readme for example. | ||
## [Unreleased] | ||
## [0.3.0] | ||
@@ -5,0 +5,0 @@ - Moved here from `fl-redux-utils` and `fl-utils` |
'use strict'; | ||
exports.__esModule = true; | ||
exports['default'] = fetchComponentData; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = fetchComponentData; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _lodash = require('lodash'); | ||
@@ -12,4 +12,2 @@ | ||
// eslint-disable-line | ||
var _queueAsync = require('queue-async'); | ||
@@ -19,34 +17,60 @@ | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var defaults = { | ||
parallelism: 1 | ||
}; | ||
/* | ||
* @param store the current redux store | ||
* @param branch the matching react-router routes | ||
* @param action the action that has triggered this fetch | ||
* @param parallelism the number of fetches to execute in parallel | ||
*/ | ||
}; // eslint-disable-line | ||
function fetchComponentData(options, callback) { | ||
var _$defaults = _lodash2['default'].defaults(options, defaults); | ||
var _$defaults = _lodash2.default.defaults(options, defaults), | ||
store = _$defaults.store, | ||
branch = _$defaults.branch, | ||
action = _$defaults.action, | ||
parallelism = _$defaults.parallelism; | ||
var store = _$defaults.store; | ||
var components = _$defaults.components; | ||
var action = _$defaults.action; | ||
var parallelism = _$defaults.parallelism; | ||
var result = {}; | ||
var queue = new _queueAsync2['default'](parallelism); | ||
var queue = new _queueAsync2.default(parallelism); | ||
components.forEach(function (_Component) { | ||
if (!_Component) return; | ||
var Component = _Component.WrappedComponent || _Component; | ||
if (!Component.fetchData) return; | ||
queue.defer(function (callback) { | ||
return Component.fetchData({ store: store, action: action }, function (err, res) { | ||
if (res) _lodash2['default'].extend(result, res); | ||
callback(err); | ||
return new Promise(function (resolve, reject) { | ||
branch.forEach(function (branch) { | ||
var Component = branch.route.component; | ||
if (!Component) return; | ||
while (Component.WrappedComponent) { | ||
Component = Component.WrappedComponent; | ||
} | ||
if (!Component.fetchData) return; | ||
var match = branch.match; | ||
queue.defer(function (callback) { | ||
var done = function done(err) { | ||
var res = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
if (res) _lodash2.default.extend(result, res); | ||
callback(err); | ||
}; | ||
var promise = Component.fetchData({ store: store, action: action, match: match }, done); | ||
if (promise) { | ||
promise.then(function (res) { | ||
return done(null, res); | ||
}).catch(function (err) { | ||
return done(err); | ||
}); | ||
} | ||
}); | ||
}); | ||
}); | ||
queue.await(function (err) { | ||
if (callback) callback(err, result); | ||
queue.await(function (err) { | ||
if (callback) callback(err, result); | ||
if (err) reject(err);else resolve(result); | ||
}); | ||
}); | ||
} | ||
module.exports = exports['default']; |
'use strict'; | ||
exports.__esModule = true; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.fetchComponentDataMiddleware = exports.fetchComponentData = undefined; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _fetchComponentData = require('./fetchComponentData'); | ||
@@ -15,3 +16,5 @@ | ||
exports.fetchComponentData = _fetchComponentData2['default']; | ||
exports.fetchComponentDataMiddleware = _middleware2['default']; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
exports.fetchComponentData = _fetchComponentData2.default; | ||
exports.fetchComponentDataMiddleware = _middleware2.default; |
'use strict'; | ||
exports.__esModule = true; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = createFetchComponentDataMiddlware; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _lodash = require('lodash'); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
var _reactRouterConfig = require('react-router-config'); | ||
var _fetchComponentData = require('./fetchComponentData'); | ||
@@ -11,23 +18,30 @@ | ||
//import {ROUTER_DID_CHANGE} from 'redux-router' // copied here to avoid a dependency | ||
var ROUTER_DID_CHANGE = '@@reduxReactRouter/routerDidChange'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var routeChangeTypes = ['@@reduxReactRouter/routerDidChange', '@@router/LOCATION_CHANGE']; | ||
var locsEqual = function locsEqual(locA, locB) { | ||
return locA.pathname === locB.pathname && locA.search === locB.search; | ||
return locA && locB && locA.pathname === locB.pathname && locA.search === locB.search; | ||
}; | ||
exports['default'] = function (store) { | ||
return function (next) { | ||
return function (action) { | ||
var router = store.getState().router; | ||
if (action.type === ROUTER_DID_CHANGE && router && !locsEqual(action.payload.location, router.location)) { | ||
var components = action.payload.components; | ||
function createFetchComponentDataMiddlware(getRoutes) { | ||
var routes = getRoutes(); | ||
_fetchComponentData2['default']({ store: store, components: components, action: action }); | ||
} | ||
next(action); | ||
return function (store) { | ||
return function (next) { | ||
return function (action) { | ||
var router = store.getState().router; | ||
if (router.location && _lodash2.default.includes(routeChangeTypes, action.type)) { | ||
if (locsEqual(action.payload.location, router.location)) return; | ||
var branch = (0, _reactRouterConfig.matchRoutes)(routes, action.payload.pathname); | ||
(0, _fetchComponentData2.default)({ store: store, branch: branch, action: action }); | ||
} | ||
next(action); | ||
}; | ||
}; | ||
}; | ||
}; | ||
} | ||
module.exports = exports['default']; |
{ | ||
"name": "fetch-component-data", | ||
"version": "0.3.2", | ||
"version": "5.0.0", | ||
"description": "Small util functions for Frameworkstein", | ||
@@ -23,14 +23,9 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"lodash": "^4.0.0", | ||
"queue-async": "^1.0.7", | ||
"lodash": "^4.0.0" | ||
"react-router-config": "^1.0.0-beta.4" | ||
}, | ||
"devDependencies": { | ||
"babel": "^5.8.29", | ||
"babel-eslint": "^4.1.3", | ||
"eslint": "^1.5.1", | ||
"eslint-config-founderlab": "^0.1.0", | ||
"eslint-plugin-react": "^3.4.2", | ||
"expect": "^1.12.2", | ||
"sinon": "^1.17.4" | ||
"babel-cli": "^6.0.0" | ||
} | ||
} |
# fetch-component-data | ||
Data fetching helper and Redux middlware for React components in Frameworkstein apps | ||
fetchComponentData | ||
fetchComponentDataMiddleware | ||
------------------ | ||
Call Component.fetchData on a list of React Components. | ||
Redux middleware to ensure container components get a chance to load their data when they're mounted. | ||
Detects `redux-router` or `react-router-redux` route change actions and calls `fetchComponentData` on the component of the route that is being navigated to. | ||
Used to tie in the data loading story for Frameworkstein. | ||
This middleware is much the same as adding a call to `fetchData` in each component's `componentDidMount` function. | ||
fetchComponentDataMiddleware | ||
fetchComponentData | ||
------------------ | ||
Redux middleware to ensure container components get a chance to load their data when they're mounted. | ||
Detects `redux-router` route change actions and calls fetchComponentData with the component of the route that is being navigated to. | ||
Calls Component.fetchData on a list of React Components. Used to tie in the data loading story for Frameworkstein. | ||
Best used in conjunction with [redux-request-middleware](https://github.com/frameworkstein/redux-request-middleware) or another method of returning a promise from dispatched actions. See there for more detailed docs. | ||
Used internally by `fl-react-server`. | ||
There's no magic here, just a convenience function that enforces the `fetchData` convention. | ||
```javascript | ||
// MyPage.js | ||
export default class MyPage extends React.Component { | ||
// Middleware will call this method on each route change | ||
// The store is provided, we can get the current state of the router from it via redux-router | ||
// We'll also need its dispatch method to dipatch actions from here | ||
// May return a promise or call the given callback function. Only useful if doing server side rendering, so the server renderer can delay rendering the page until the component has finished loading its data. | ||
static fetchData({store, action}/*, callback*/) { | ||
// As is the current action if we're transitioning between routes. 'action.payload' contains the props for the route we're transitioning to. Here for example we're getting router.params.id from it | ||
const {router} = store.getState() | ||
const id = ((action && action.payload && action.payload.params) || router.params).id | ||
// Assuming we're using redux-request-middleware to return a promise when dispatching this action | ||
return store.dispatch(loadMyPageContent()) | ||
} | ||
// ...rest of the component goes below | ||
render() { | ||
// ...etc | ||
} | ||
} | ||
``` | ||
``` |
import _ from 'lodash' // eslint-disable-line | ||
import Queue from 'queue-async' | ||
const defaults = { | ||
@@ -8,20 +9,43 @@ parallelism: 1, | ||
/* | ||
* @param store the current redux store | ||
* @param branch the matching react-router routes | ||
* @param action the action that has triggered this fetch | ||
* @param parallelism the number of fetches to execute in parallel | ||
*/ | ||
export default function fetchComponentData(options, callback) { | ||
const {store, components, action, parallelism} = _.defaults(options, defaults) | ||
const {store, branch, action, parallelism} = _.defaults(options, defaults) | ||
const result = {} | ||
const queue = new Queue(parallelism) | ||
components.forEach(_Component => { | ||
if (!_Component) return | ||
const Component = _Component.WrappedComponent || _Component | ||
if (!Component.fetchData) return | ||
queue.defer(callback => Component.fetchData({store, action}, (err, res) => { | ||
if (res) _.extend(result, res) | ||
callback(err) | ||
})) | ||
}) | ||
return new Promise((resolve, reject) => { | ||
branch.forEach(branch => { | ||
let Component = branch.route.component | ||
if (!Component) return | ||
queue.await(err => { | ||
if (callback) callback(err, result) | ||
while (Component.WrappedComponent) { | ||
Component = Component.WrappedComponent | ||
} | ||
if (!Component.fetchData) return | ||
const match = branch.match | ||
queue.defer(callback => { | ||
const done = (err, res={}) => { | ||
if (res) _.extend(result, res) | ||
callback(err) | ||
} | ||
const promise = Component.fetchData({store, action, match}, done) | ||
if (promise) { | ||
promise.then(res => done(null, res)).catch(err => done(err)) | ||
} | ||
}) | ||
}) | ||
queue.await(err => { | ||
if (callback) callback(err, result) | ||
if (err) reject(err) | ||
else resolve(result) | ||
}) | ||
}) | ||
} |
import fetchComponentData from './fetchComponentData' | ||
import fetchComponentDataMiddleware from './middleware' | ||
export {fetchComponentData, fetchComponentDataMiddleware} | ||
export { fetchComponentData, fetchComponentDataMiddleware } |
@@ -0,14 +1,28 @@ | ||
import _ from 'lodash' | ||
import { matchRoutes } from 'react-router-config' | ||
import fetchComponentData from './fetchComponentData' | ||
//import {ROUTER_DID_CHANGE} from 'redux-router' // copied here to avoid a dependency | ||
const ROUTER_DID_CHANGE = '@@reduxReactRouter/routerDidChange' | ||
const locsEqual = (locA, locB) => (locA.pathname === locB.pathname) && (locA.search === locB.search) | ||
export default store => next => action => { | ||
const router = store.getState().router | ||
if (action.type === ROUTER_DID_CHANGE && router && !locsEqual(action.payload.location, router.location)) { | ||
const {components} = action.payload | ||
fetchComponentData({store, components, action}) | ||
const routeChangeTypes = [ | ||
'@@reduxReactRouter/routerDidChange', | ||
'@@router/LOCATION_CHANGE', | ||
] | ||
const locsEqual = (locA, locB) => locA && locB && (locA.pathname === locB.pathname) && (locA.search === locB.search) | ||
export default function createFetchComponentDataMiddlware(getRoutes) { | ||
const routes = getRoutes() | ||
return store => next => action => { | ||
const router = store.getState().router | ||
if (router.location && _.includes(routeChangeTypes, action.type)) { | ||
if (locsEqual(action.payload.location, router.location)) return | ||
const branch = matchRoutes(routes, action.payload.pathname) | ||
fetchComponentData({store, branch, action}) | ||
} | ||
next(action) | ||
} | ||
next(action) | ||
} |
import expect from 'expect' | ||
import {spy} from 'sinon' | ||
import {fetchComponentData} from '../src' | ||
import { spy } from 'sinon' | ||
import { fetchComponentData } from '../src' | ||
describe('fetchComponentData', () => { | ||
@@ -6,0 +7,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
12551
1
200
1
53
3
+ Added@babel/runtime@7.26.0(transitive)
+ Addedhistory@4.10.1(transitive)
+ Addedhoist-non-react-statics@2.5.5(transitive)
+ Addedinvariant@2.2.4(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedloose-envify@1.4.0(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedpath-to-regexp@1.9.0(transitive)
+ Addedprop-types@15.8.1(transitive)
+ Addedreact@18.3.1(transitive)
+ Addedreact-is@16.13.1(transitive)
+ Addedreact-router@4.3.1(transitive)
+ Addedreact-router-config@1.0.0-beta.4(transitive)
+ Addedregenerator-runtime@0.14.1(transitive)
+ Addedresolve-pathname@3.0.0(transitive)
+ Addedtiny-invariant@1.3.3(transitive)
+ Addedtiny-warning@1.0.3(transitive)
+ Addedvalue-equal@1.0.1(transitive)
+ Addedwarning@4.0.3(transitive)