Skip to main content

shallowObjectEqualityCheck

Shallow equality check for objects with primitive property values. Compares each property's value rather than object reference.

When to Use

Use when deriving objects where all properties are primitives (string, number, boolean):

Signature

typescript
function shallowObjectEqualityCheck(): (current: ObjectWithImmutables) => boolean
type ObjectWithImmutables = Record<string, string | number | boolean>

Basic Usage

tsx
import { shallowObjectEqualityCheck } from '@react-facet/core'
 
const equalityCheck = shallowObjectEqualityCheck()
 
equalityCheck({ name: 'Alex', height: 2 })
 
console.log(equalityCheck({ name: 'Alex', height: 2 })) // true - same values
console.log(equalityCheck({ name: 'Steve', height: 2 })) // false - different name
console.log(equalityCheck({ name: 'Steve', height: 2 })) // true - same values again

Usage with Facets

Combining Multiple Facets

tsx
import { useFacetMap, useFacetWrap, shallowObjectEqualityCheck } from '@react-facet/core'
 
const PlayerStats = () => {
const nameFacet = useFacetWrap('Steve')
const healthFacet = useFacetWrap(100)
const levelFacet = useFacetWrap(5)
 
// Combine into single object - only updates when values actually change
const playerStatsFacet = useFacetMap(
(name, health, level) => ({ name, health, level }),
[],
[nameFacet, healthFacet, levelFacet],
shallowObjectEqualityCheck, // Prevents updates from object recreation
)
 
return (
<div>
<fast-text text={useFacetMap((stats) => `${stats.name} - Level ${stats.level}`, [], [playerStatsFacet])} />
</div>
)
}

Nullable Variant

For cases where the entire object might be null or undefined, use nullableShallowObjectEqualityCheck:

tsx
import { nullableShallowObjectEqualityCheck } from '@react-facet/core'
 
const equalityCheck = nullableShallowObjectEqualityCheck()
 
equalityCheck(null)
console.log(equalityCheck(null)) // true - null === null ✅
 
console.log(equalityCheck({ name: 'Steve', age: 25 })) // false - null → object ❌
 
console.log(equalityCheck({ name: 'Steve', age: 25 })) // true - same object values ✅
 
console.log(equalityCheck(null)) // false - object → null ❌
tip

For objects with nullable properties (like { name: string | null }), you don't need the nullable variant. Regular shallowObjectEqualityCheck handles null/undefined property values just fine using strict equality (===).

How It Works

The equality check:

  1. Compares the number of keys in both objects
  2. Iterates through each property
  3. Compares primitive values using ===
  4. Returns false if any property differs
tsx
import { shallowObjectEqualityCheck } from '@react-facet/core'
 
const check = shallowObjectEqualityCheck()
 
check({ a: 1, b: 'hello' })
 
// Different object reference, but same values
console.log(check({ a: 1, b: 'hello' })) // true ✅
 
// Different values
console.log(check({ a: 2, b: 'hello' })) // false ❌
 
// Different keys
console.log(check({ a: 1, b: 'hello', c: 'extra' })) // false ❌

Important Notes

Only Shallow Comparison

This check does not compare nested objects or arrays:

tsx
import { shallowObjectEqualityCheck } from '@react-facet/core'
 
// ❌ Won't work as expected for nested structures
const check = shallowObjectEqualityCheck()
 
const nested1 = { user: { name: 'Steve' } }
const nested2 = { user: { name: 'Steve' } } // Different object reference
 
// @ts-expect-error - Type error: user property is an object, not a primitive
check(nested1)
// @ts-expect-error - Type error: user property is an object, not a primitive
console.log(check(nested2)) // false - user objects have different references

Note: TypeScript will catch this mistake - the equality check expects objects with only primitive values (string | number | boolean).

For nested structures, use:

Property Order Doesn't Matter

tsx
import { shallowObjectEqualityCheck } from '@react-facet/core'
 
const check = shallowObjectEqualityCheck()
 
check({ name: 'Alex', age: 25 })
 
// Same values, different order - still equal
console.log(check({ age: 25, name: 'Alex' })) // true ✅

Common Patterns

Form State

tsx
import { useFacetMap, shallowObjectEqualityCheck } from '@react-facet/core'
const formStateFacet = useFacetMap(
(username, email, age) => ({ username, email, age }),
[],
[usernameFacet, emailFacet, ageFacet],
shallowObjectEqualityCheck,
)

Computed Properties

tsx
import { useFacetMap, shallowObjectEqualityCheck } from '@react-facet/core'
const statsViewFacet = useFacetMap(
(player) => ({
displayName: player.name.toUpperCase(),
healthPercent: (player.health / player.maxHealth) * 100,
isLowHealth: player.health < 20,
}),
[],
[playerFacet],
shallowObjectEqualityCheck,
)

API Response Transformation

tsx
import { useFacetMap, shallowObjectEqualityCheck } from '@react-facet/core'
const parsedResponseFacet = useFacetMap(
(rawData) => ({
id: parseInt(rawData.id),
name: rawData.name.trim(),
active: rawData.status === 'active',
}),
[],
[rawDataFacet],
shallowObjectEqualityCheck,
)

See Also