The Redux site mentions that we should avoid putting non-serializable values in state or actions. But what exactly does Redux consider serializable?
Digging through the Redux source code reveals the use of an isSerializable
function that the createSerializableStateInvariantMiddleware
function takes as an optional parameter.
By default, Redux will assign an isPlain
function to isSerializable
.
Let's see how exactly isPlain
is implemented.
The following code shows shows that serializable means that it can be serialized to JSON. This includes boolean, number, string, array, plain object or undefined
.
/**
* Returns true if the passed value is "plain", i.e. a value that is either
* directly JSON-serializable (boolean, number, string, array, plain object)
* or `undefined`.
*
* @param val The value to check.
*
* @public
*/
export function isPlain(val: any) {
const type = typeof val
return (
type === 'undefined' ||
val === null ||
type === 'string' ||
type === 'boolean' ||
type === 'number' ||
Array.isArray(val) ||
isPlainObject(val)
)
}
/**
* Returns true if the passed value is "plain" object, i.e. an object whose
* prototype is the root `Object.prototype`. This includes objects created
* using object literals, but not for instance for class instances.
*
* @param {any} value The value to inspect.
* @returns {boolean} True if the argument appears to be a plain object.
*
* @public
*/
export default function isPlainObject(value: unknown): value is object {
if (typeof value !== 'object' || value === null) return false
let proto = value
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}
// In Node.js, the root `Object.prototype` is `[Object: null prototype] {}`
return Object.getPrototypeOf(value) === proto
}