
Security News
MCP Steering Committee Launches Official MCP Registry in Preview
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.
redux-resx
Advanced tools
(Yet another) Redux action creators, a reducer and middleware for resource-based APIs
Yet another Redux action creators, a reducer and middleware for resource-based APIs.
resx = shortening for resource
Based on the async actions pattern in redux (https://redux.js.org/docs/advanced/AsyncActions.html)
npm install --save redux-resx
A resource is a grouping of redux reducers, actions and selectors for your api endpoint. You define a unique name for it and the url. You can also add your own reducer to augment the state at the "mountpoint" on the state store.
// somewhere like src/resources/user.js
import createResource from 'redux-resx';
export default createResource({
// Required:
name: '@resx/USER', // Unique namespace for actions and reducer
url: '/users',
// Optional (defaults shown)
// This function should return the root object of where you mount your state
baseSelector: s => s.resources,
// Use this to add extra reducers which receive the state after the built-in reducer
// has done it's thing - this can perhaps be used in conjunction with custom middleware
// It only receives resource actions, not every action
reducer: (state, _action) => state,
});
// src/resources/index.js
export default as user from './user';
import { combineReducers } from 'redux';
import * as resources from '../resources';
import { reducer as resourceReducer } from 'redux-resx';
export default combineReducers({
resources: combineReducers(resourceReducer(resources)),
});
Lets break this down a bit:
export default combineReducers({
// 'resources' can be anywhere, you just need to specify a base selector that selects it in
// create resource
resources: combineReducers(
// resourceReducer is really just transforms the object to something that combineReducers can use
// Give it { users: [result of createResource] } and it will return { users: reducerFn } - simple
resourceReducer(resources)
),
});
// Another way you could do this
import userResource from '../resources/users';
...
resources: combineReducers({
myUser: userResource.reducer,
//etc
})
Please see the NB comments
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { user as userResx } from '../resources';
// NB: New in 1.0.0+
// *************************************************************************
// You need to provide a namespace for your 'instance' (any string) that you want to use.
// This is so you can call a resource in multiple components without interferance.
const myUserResx = userResx.create('@HOME');
// If you omit the namespace, a default one will be used (essentially the same behaviour prior to 1.0.0)
// const myUserResx = userResx.create();
// Using the default method, returns a singleton instance for reuse
// const myUserResx = userResx.default();
const Home = React.createClass({
//....
componentWillMount() {
const { getUser, findUsers, resetUsers } = this.props;
// XXX: Optional, you'll get old results before new ones are loaded if you don't do this.
// New in 1.0.0: If your resource is only used in this component and you destroy on unmount,
// you definitely/obviously won't need to use reset.
resetUsers();
findUsers({ status: 'active' }); // params of request
getUser(123).then(...); // id=123 NB: only if middleware returns a promise
},
// NB: New in 1.0.0 - will remove the namespaced data entirely
componentWillUnmount() {
this.props.destroyResx();
}
render() {
const { users, user } = this.props;
return (
<div>
{users ? JSON.stringify(users) : null}
{user ? JSON.stringify(user) : null}
</div>
);
},
});
function mapStateToProps(state) {
// Select the resource state
const {
hasLoaded, // true when find has been loaded before
isBusy, // true when any of the following are true
isFinding,
isGetting,
isCreating,
isUpdating,
isPatching,
isRemoving,
// Result for find - always an array (initial value: [])
items,
// Last result for create, get, update, patch, remove
entity, // (initial value: undefined)
} = userResx.selector(state);
return {
users: items,
user: entity,
isBusy,
};
}
const { find: findUsers, get: getUser, reset: resetUsers, destroy: destroyResx } = myUserResx.actions;
export default connect(mapStateToProps, {
findUsers,
getUser,
resetUsers,
destroyResx,
})(Home);
Each resx
has a selector function which can be used to select the resource from the state store.
A resx
has the following structure:
// Initial structure of resx
{
hasLoaded: false, // Has the resource loaded before (has find returned a result and items populated)
isBusy: false, // true if any operation is running on this resx, otherwise false
isFinding: false, // true if find call is busy, otherwise false
isGetting: false, // true if get call is busy, otherwise false
isCreating: false, // true if create call is busy, otherwise false
isUpdating: false, // true if update call is busy, otherwise false
isPatching: false, // true if patch call is busy, otherwise false
isRemoving: false, // true if remove call is busy, otherwise false
items: [], // The result of a find call
entity: undefined, // The result of the last get, create, patch, update and remove call
lastError: undefined, // The result of the call if it was an error
}
The middleware's job is to "handle" the actions coming in from resource action creators. This is where the side-effects are. A middleware is included which calls endpoints like you would expect, but you can implement your own or use e.g. sagas.
Add middleware to store in the normal way
// NB: Only bundled if you are using it
import middleware from 'redux-resx/middleware';
import fetch from 'isomorphic-fetch';
//... other imports
const resxMiddleware = middleware({
baseUrl: '/api',
provider: fetch, // could write adapter to convert fetch params to e.g. request/jquery
});
export default function createApplicationStore() {
return createStore(
reducers,
compose(applyMiddleware(resxMiddleware))
);
}
feathers-client
to make requestsFAQs
(Yet another) Redux action creators, a reducer and middleware for resource-based APIs
We found that redux-resx demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.
Product
Socket’s new Pull Request Stories give security teams clear visibility into dependency risks and outcomes across scanned pull requests.
Research
/Security News
npm author Qix’s account was compromised, with malicious versions of popular packages like chalk-template, color-convert, and strip-ansi published.