Tiny library for validating redux actions with some built-in and customizible rules.
How has that problem appeared? Working on complex client app written in js with redux usage you may want to use different technics that impose some restrictions on the redux store state.
- Want to rehydrate store after SSR(Server Side Rendering)?
- Want to persist temporary state in LocalStorage for next re-usage?
- Want to use Event Sourcing approach to be able to restore your app state?
Well, in that case we have to have got serializible store. Actually the original redux FAQ recommends it:
Can I put functions, promises, or other non-serializable items in my store state?
It is highly recommended that you only put plain serializable objects, arrays, and primitives into your store. It's technically possible to insert non-serializable items into the store, but doing so can break the ability to persist and rehydrate the contents of a store, as well as interfere with time-travel debugging.
If you are okay with things like persistence and time-travel debugging potentially not working as intended, then you are totally welcome to put non-serializable items into your Redux store. Ultimately, it's your application, and how you implement it is up to you. As with many other things about Redux, just be sure you understand what tradeoffs are involved.
But we are human and can't spot problem easily. Take the most popular devtools for redux redux-devtools
has the next warning:
Symbols or other unserializable data not shown:
To get data which cannot be serialized by JSON.stringify, set serialize parameter. ... It will handle also date, regex, undefined, error objects, symbols, maps, sets and functions.
So devtools try to handle that case carefully and anyway next issues could be found in redux-devtools
for 5 minutes of searching:
handling circlar references:
serialization
Now, when we aware of trade-offs, probably we want to keep store as much serializable as we can. And let the machine lint the aforementioned problems for us.
install npm i blablabla
add the middleware and configure for your needs:
import createReduxActionValidationMiddleware from 'redux-action-validator';
const ignoredTypes = [
/^redux-form/
];
// setup ignoring for some actions
const shouldIgnore = action => ignoredTypes.some(rx => rx.test(action.type));
function logInvalidAction(actionObject) {
console.error('Redux action is not valid', actionObject);
}
function logValidationError(error) {
console.error(
[
`rule: ${error.rule}`,
`path: ${error.path}`,
`message: ${error.message}`
].join('\n')
);
}
// format error as you need
function onError(action, errors) {
console.group('validation error');
logInvalidAction(action);
errors.forEach(logValidationError);
console.groupEnd();
};
const reduxActionValidationMiddleware = createReduxActionValidationMiddleware({
validatorOptions: { shouldIgnore },
onError
});
...
const middlewares = [reduxActionValidationMiddleware, ...];
const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(...middlewares)
...
To adjust options to your need pass option object when creating a middleware.
createReduxActionValidationMiddleware({ validatorOptions, onError })
Next interfaces are used by the utility:
ErrorDescription {
rule: string; // used to setup rule name
path: string; // used to pass problem property. root object is denoted as $ sign
message: string; // used to be logged as extended message desciption
}
ValidationRule {
isValid: (action: object) => bool; // validate passed action. reutrn valse if not valid
getDescription(path: string) => ErrorDescription; // return error description
}
shouldIgnore: (action) => bool
filter actions that shouldn't be validated
ignoreCircularRefs: bool
ignore circular reference errors
validateAction: ValidationRule || null
Passing null
you can disable default action validation implementation. By default, we only validate that action meets FSA requirements.
Also, you can adjust your own validation rule instead by passing an object with ValidationRule
interface.
validateProps: ValidationRule || null
Passing null
you can disable default action properties validation implementation. By default we validate all properties are plain javascript objects (POJO).
Also, you can adjust your own validation rule instead by passing an object with ValidationRule
interface.
validateProps: ValidationRule || null
You can extend default settings with your own validation rule by passing an object with ValidationRule
interface.
(errors: ErrorDescription[]) => void
callback called with validation errors