Research
Security News
Malicious PyPI Package ‘pycord-self’ Targets Discord Developers with Token Theft and Backdoor Exploit
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
@ackee/chris
Advanced tools
Useful additions for your redux - react-router based app.
Name of package refers to Saint Christopher, patron of travellers at their routes. Chris is just its shorter form used for easier remembrance and writability.
Using npm:
npm i -s @ackee/chris
Using yarn:
yarn add @ackee/chris
routingSelector
Selector for connected-react-router
state, which returns location
.
runRouteDependencies(handlers: {[ActionType], sagaHandler}, selector: ReduxSelector)
With usage of runRouteDependencies
and routing-history
, you can exclude business logic from React componentDidMount
and componentWillUnmount
and download the data you need for the current page outside of React components.
Example - react to new route
import { runRouteDependencies } from '@ackee/chris';
const handlers = {
'/user/:id': function* ({ id }) {
// fetch user data and store it
}
};
export default function* () {
yield all([
takeEvery(LOCATION_CHANGE, runRouteDependencies, handlers),
])
}
Example - react to new route and clean data when leaving it
import { runRouteDependencies } from '@ackee/chris';
import routingHistory from '@ackee/chris/routing-history';
const { activeLocationSelectorFactory, previousLocationSelectorFactory } = routingHistory;
// 'history' is the name of routingHistory module state
const activeLocationSelector = activeLocationSelectorFactory('history');
const previousLocationSelector = previousLocationSelectorFactory('history');
const handlers = {
'/user/:id': function* ({ id }) {
// fetch user data and store it
}
};
const postHandlers = {
'/user/:id': function* ({ id }) {
// flush user data from the store
}
};
export default function* () {
yield all([
takeEvery(LOCATION_CHANGE, runRouteDependencies, handlers, activeLocationSelector),
takeEvery(LOCATION_CHANGE, runRouteDependencies, postHandlers, previousLocationSelector),
])
}
runRouteActions(handlers: {[ActionType], sagaHandler})
Alias for runRouteDependencies
saga.
routeRefresh(initType: ActionType, type: ActionType, handlers: function)
TBD
runSagas(sagas: {[ActionType]: sagaHandler})
TBD
There is a routing history module for handling history in redux & react-router apps called routingHistory
import routingHistory from '@ackee/chris/routing-history';
combineDependenciesHandlers(...routeHandlers) => combinedRouteHandlers
Helper to combine dependencies handlers for runRouteDependecies
. Accepts infinite number of handlers objects ({'template': sagaHandler})
and returns exactly one for usage in runRouteDependecies
. Supports same keys in the handlers objects
import { routeHandlers as usersHandlers } from 'Modules/users';
import { routeHandlers as reviewsHandlers } from 'Modules/reviews';
export const appHandlers = {
'/': homeSaga,
'/logout': function* () {
// ...
},
};
const combinedRouteHandlers = combineDependenciesHandlers(
appHandlers,
usersHandlers,
reviewsHandlers
);
runRouteDependencies(combinedRouteHandlers);
Each module (e.g. Modules/users
) may exports its own routeHandlers
object and the combineDependenciesHandlers
utility handles their merging.
fetchDependencies(config?: Config) => (Component) => ComponentThatFetchDependencies
High order component used to request data for wrapped component. If you wrap your page components with the HOC it will ensure that data it needs will be requested right after component render.
In default HOC calls fetch
function passed through props when component mounts and clear
before it unmounts. If it doesn't suit your needs, supply a config that define your own way of handling. All methods in config are optional and if they aren't supplied, default ones are used.
interface Config {
onLoad?: (props) => void;
onUnload?: (props) => void;
shouldReFetch?: (prevProps, nextProps) => boolean;
}
const UsersListPageContainer = compose(
connect(
state => ({ users: state.users }),
dispatch => bindActionCreators({
fetch: requestUsers,
clear: deleteUsers
}, dispatch),
),
fetchDependencies(),
)(UsersListPage);
const App = () => (
<div>
<UserListPageContainer />
</div>
);
const UserDetailPageContainer = compose(
connect(
(state: State) => ({
user: state.user,
userId: state.selectedUserId
}),
dispatch => bindActionCreators({
requestUserDetail: requestUser,
clearUserDetail: clearUser,
}, dispatch),
),
fetchDependencies({
onLoad: ({ userId, requestUserDetail }) => {
requestUserDetail(userId);
},
onUnload: ({ clearUserDetail }) => {
clearUserDetail();
},
shouldReFetch: (prevProps, props) => {
return prevProps.userId !=== props.userId;
},
}),
)(UserDetailPage);
const App = () => (
<div>
<UserListPageContainer />
</div>
);
routeDependencies(config?: Config) => (Component) => ComponentWithRouteDependencies
Important prerequistence for using the HOC is that you must have
react-router
in your app.
HOC has same purpose and works almost same as fetchDependencies
with few exceptions.
withRouter
HOC so all props receive also router's match
, location
and history
objects.interface Config {
onRouteEnter?: (props) => void;
onRouteLeave?: (props) => void;
shouldReRoute?: (prevProps, nextProps) => boolean;
}
shouldReRoute
invoke refetch of data every time any part of url change. It's used until you provide your own.const UsersListPageContainer = compose(
connect(
state => ({ users: state.users }),
dispatch => bindActionCreators({
fetch: requestUsers,
clear: deleteUsers
}, dispatch),
),
routeDependencies(),
)(UsersListPage);
const App = () => (
<Router>
<div>
<Route path="/users" component={UserListPageContainer}/>
</div>
</Router>
);
const UserDetailPageContainer = compose(
connect(
(state: State) => ({ user: state.user }),
dispatch => bindActionCreators({
requestUserDetail: requestUser,
clearUserDetail: clearUser,
}, dispatch),
),
routeDependencies({
onRouteEnter: ({ match, requestUserDetail }) => {
requestUserDetail(match.params.id);
},
onRouteLeave: ({ match, clearUserDetail }) => {
clearUserDetail();
},
shouldReRoute: (prevProps, props) => {
return prevProps.match.params.id !=== props.match.params.id;
},
}),
)(UserDetailPage);
const App = () => (
<Router>
<div>
<Route path="/users/:id" component={UserDetailPageContainer}/>
</div>
</Router>
);
FAQs
Useful additions for your redux - react-router based app
The npm package @ackee/chris receives a total of 26 weekly downloads. As such, @ackee/chris popularity was classified as not popular.
We found that @ackee/chris demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 6 open source maintainers 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.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.
Security News
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.