Skip to main content

Equality

Overview

Some common equality-checking presets that can be used with useStateValue and useStateValueWithReactiveSelector or for any general purpose.

Presets

shallowCompareArray

Compares each element in the array using Object.is. Use this when your selector returns an array.

shallowCompareArray(
previousState: Array<any> | any,
nextState: Array<any> | any
): boolean

Plain Example

React Example

import { Equality, StateManager } from 'cotton-box'
import { useStateValue } from 'cotton-box-react'

const ExampleState = new StateManager({
foo: '...',
bar: '...',
})

function App(): JSX.Element {
const state = useStateValue(
ExampleState,
(state) => [state.foo, state.bar],
Equality.shallowCompareArray
)
return '...'
}
info

Each time the selector runs, a new array is returned. By default, Object.is is used to compare the previous and next states. So even if the length of array and the elements that it contains do not change, they will still be treated as "not equal" and cause unnecessary re-rendering in components.

shallowCompareObject

Compares each item in the object using Object.is. Use this when your selector returns a plain object.

shallowCompareObject(previousState: any, nextState: any): boolean

Plain Example

React Example

import { Equality, StateManager } from 'cotton-box'
import { useStateValue } from 'cotton-box-react'

const ExampleState = new StateManager({
foo: '...',
bar: '...',
})

function App(): JSX.Element {
const state = useStateValue(
ExampleState,
(state) => ({ foo: state.foo, bar: state.bar }),
Equality.shallowCompareObject
)
return '...'
}
info

Each time the selector runs, a new object is returned. By default, Object.is is used to compare the previous and next states. So even if the number of key-value pairs, their contents, and how they are ordered do not change, the previous and next states will still be treated as "not equal" and cause unnecessary re-rendering in components.

shallowCompareArrayOrObject

A wrapper around shallowCompareArray and shallowCompareObject. Only use this when you cannot determine whether your selected state will return an array or an object as it exhausts additional computing resources that could otherwise be prevented.

shallowCompareArrayOrObject(
previousState: Array<any> | any,
nextState: Array<any> | any
): boolean

Plain Example

React Example

import { Equality, StateManager } from 'cotton-box'
import { useStateValue } from 'cotton-box-react'

const ExampleState = new StateManager({
foo: '...',
bar: '...',
baz: '...',
qux: '...',
someFlag: true,
})

const complexSelector = (state) => {
if (state.someFlag) {
return [
state.foo,
state.bar,
]
} else {
return {
baz: state.baz,
qux: state.qux,
}
}
}

function App(): JSX.Element {
const state = useStateValue(
ExampleState,
complexSelector,
Equality.shallowCompareArrayOrObject
)
return '...'
}

stringifyCompare

Compares the previous and next states after serializing them with JSON.stringify.

stringifyCompare(previousState: any, nextState: any): boolean

Plain Example

React Example

import { Equality, StateManager } from 'cotton-box'
import { useStateValue } from 'cotton-box-react'

const ExampleState = new StateManager({
foo: new Date('...'),
bar: '...',
})

function App(): JSX.Element {
const state = useStateValue(
ExampleState,
(state) => state.foo,
Equality.stringifyCompare
)
return '...'
}
warning

The example above is just for demonstration. Avoid using JSON.stringify to compare states because it usually comes with a higher computing overhead as the states will first need to be serialized into strings before their values can be compared.

Instead, prefer using custom functions that are tailored to the shape of your state. This would be a more practical rewrite of the example above:

const state = useStateValue(
ExampleState,
(state) => state.foo,
(prevState, nextState) => prevState.getTime() === nextState.getTime()
)
info
What is a "shape"?

In JavaScript programs, it’s common to have multiple objects with the same property keys. Such objects have the same shape.

const object1 = { x: 1, y: 2 };
const object2 = { x: 3, y: 4 };
// `object1` and `object2` have the same shape.

Quoted from: https://mathiasbynens.be/notes/shapes-ics#shapes