createUniformObjectEqualityCheck
Creates an equality check for objects where all properties have the same type. The property values are compared using a provided equality check.
When to Use
Use when deriving objects where all properties share the same type (but not primitives):
- ✅ Objects with properties of the same complex type (arrays, nested objects)
- ✅ Uniform data structures (e.g.,
{ x: number[], y: number[], z: number[] }
) - ❌ Objects with primitive values (use
shallowObjectEqualityCheck
) - ❌ Objects with different types per property (use
createObjectWithKeySpecificEqualityCheck
)
Signature
typescript
function createUniformObjectEqualityCheck<T>(valueEqualityCheck: EqualityCheck<T>): EqualityCheck<Record<string, T>>
Parameters:
valueEqualityCheck
- Equality check to use for comparing each property value
Returns: An equality check that compares all object properties using the provided value equality check.
When using createUniformObjectEqualityCheck
with useFacetMap
or useFacetMemo
, you must create a stable reference to the equality check. If you create it inline on every render, the facet gets recreated and internal state is lost.
tsx
// ❌ WRONG - Creates new equality check on every renderconst Component = () => {const result = useFacetMap((data) => transform(data),[],[dataFacet],createUniformObjectEqualityCheck(shallowArrayEqualityCheck), // New reference every render!)}// ✅ CORRECT - Define outside componentconst dataEqualityCheck = createUniformObjectEqualityCheck(shallowArrayEqualityCheck)const Component = () => {const result = useFacetMap((data) => transform(data), [], [dataFacet], dataEqualityCheck)}// ✅ ALSO CORRECT - Use useMemo for dynamic configurationconst Component = ({ checkType }: { checkType: string }) => {const equalityCheck = useMemo(() =>createUniformObjectEqualityCheck(checkType === 'array' ? shallowArrayEqualityCheck : shallowObjectEqualityCheck),[checkType],)const result = useFacetMap((data) => transform(data), [], [dataFacet], equalityCheck)}
See Custom Equality Checks for more details.
Basic Usage
tsx
import {createUniformObjectEqualityCheck ,shallowArrayEqualityCheck } from '@react-facet/core'// Create equality check for objects with array propertiesconstequalityCheck =createUniformObjectEqualityCheck (shallowArrayEqualityCheck )()equalityCheck ({a : [1, 2],b : [3],})console .log (equalityCheck ({a : [1, 2],b : [3],}),) // true - same array valuesconsole .log (equalityCheck ({a : [1, 5],b : [3],}),) // false - array 'a' changedconsole .log (equalityCheck ({a : [1, 5],b : [3],}),) // true - same values again
Usage with Facets
Vector Data Structure
tsx
import {useMemo } from 'react'import {useFacetMap ,useFacetWrap ,createUniformObjectEqualityCheck ,shallowArrayEqualityCheck ,} from '@react-facet/core'typeVectorData = {x : number[]y : number[]z : number[]}constVectorChart = () => {constdataFacet =useFacetWrap <VectorData >({x : [1, 2, 3],y : [4, 5, 6],z : [7, 8, 9],})// ✅ Memoize equality check to maintain stable referenceconstequalityCheck =useMemo (() =>createUniformObjectEqualityCheck (shallowArrayEqualityCheck ), [])// All properties are number arraysconstnormalizedDataFacet =useFacetMap ((data ) => ({x :data .x .map ((v ) =>v / 10),y :data .y .map ((v ) =>v / 10),z :data .z .map ((v ) =>v / 10),}),[],[dataFacet ],equalityCheck ,)return <div >Vector chart</div >}
Multi-Language Translations
tsx
import {useFacetMap ,useFacetWrap ,createUniformObjectEqualityCheck ,shallowObjectEqualityCheck ,} from '@react-facet/core'typeTranslation = {title : string;description : string }typeTranslations = {en :Translation es :Translation fr :Translation }constMultiLangContent = () => {consttranslationsFacet =useFacetWrap <Translations >({en : {title : 'Welcome',description : 'Hello there' },es : {title : 'Bienvenido',description : 'Hola' },fr : {title : 'Bienvenue',description : 'Bonjour' },})// All properties are Translation objectsconstupperCaseTranslationsFacet =useFacetMap ((translations ) => ({en : {title :translations .en .title .toUpperCase (),description :translations .en .description },es : {title :translations .es .title .toUpperCase (),description :translations .es .description },fr : {title :translations .fr .title .toUpperCase (),description :translations .fr .description },}),[],[translationsFacet ],createUniformObjectEqualityCheck (shallowObjectEqualityCheck ),)return <div >Translations</div >}
Grouped Data
tsx
import {useFacetMap ,useFacetWrap ,createUniformObjectEqualityCheck ,shallowArrayEqualityCheck ,} from '@react-facet/core'typeGroupedItems = {active : number[]pending : number[]completed : number[]}constItemStats = () => {constitemsFacet =useFacetWrap ([{id : 1,status : 'active' },{id : 2,status : 'pending' },{id : 3,status : 'active' },])constgroupedIdsFacet =useFacetMap ((items ) => ({active :items .filter ((i ) =>i .status === 'active').map ((i ) =>i .id ),pending :items .filter ((i ) =>i .status === 'pending').map ((i ) =>i .id ),completed :items .filter ((i ) =>i .status === 'completed').map ((i ) =>i .id ),}),[],[itemsFacet ],createUniformObjectEqualityCheck (shallowArrayEqualityCheck ),)return <div >Item stats</div >}
How It Works
The equality check:
- Compares the number of keys in both objects
- For each property, uses the provided value equality check
- Returns
false
if any property comparison fails
tsx
import {createUniformObjectEqualityCheck ,strictEqualityCheck } from '@react-facet/core'// Using strictEqualityCheck for simple democonstcheck =createUniformObjectEqualityCheck (strictEqualityCheck )()check ({a : 1,b : 2,c : 3 })// Same valuesconsole .log (check ({a : 1,b : 2,c : 3 })) // true ✅// One value changedconsole .log (check ({a : 1,b : 5,c : 3 })) // false ❌// Different keysconsole .log (check ({a : 1,b : 2 })) // false ❌
Nesting Equality Checks
You can nest createUniformObjectEqualityCheck
for deeply uniform structures:
tsx
import {createUniformObjectEqualityCheck ,shallowArrayEqualityCheck } from '@react-facet/core'// Objects containing objects containing arraystypeDeepUniform = {region1 : {x : number[];y : number[] }region2 : {x : number[];y : number[] }}constinnerCheck =createUniformObjectEqualityCheck (shallowArrayEqualityCheck )constouterCheck =createUniformObjectEqualityCheck (innerCheck )()outerCheck ({region1 : {x : [1, 2],y : [3, 4] },region2 : {x : [5, 6],y : [7, 8] },})console .log (outerCheck ({region1 : {x : [1, 2],y : [3, 4] },region2 : {x : [5, 6],y : [7, 8] },}),) // true ✅
Important Notes
All Properties Must Have Same Type
This check assumes all properties can be compared with the same equality check:
tsx
import {createUniformObjectEqualityCheck ,shallowArrayEqualityCheck } from '@react-facet/core'// ❌ Won't work correctly - mixed typestypeMixedTypes = {numbers : number[] // Arrayname : string // Primitive - different type!}// This will fail at runtime or give incorrect resultsconstcheck =createUniformObjectEqualityCheck (shallowArrayEqualityCheck )()
For mixed types, use createObjectWithKeySpecificEqualityCheck
.
Property Order Doesn't Matter
tsx
import {createUniformObjectEqualityCheck ,strictEqualityCheck } from '@react-facet/core'constcheck =createUniformObjectEqualityCheck (strictEqualityCheck )()check ({a : 1,b : 2 })// Same values, different orderconsole .log (check ({b : 2,a : 1 })) // true ✅
Common Patterns
Chart Data (Multiple Series)
tsx
import { useFacetMap, createUniformObjectEqualityCheck, shallowArrayEqualityCheck } from '@react-facet/core'const chartDataFacet = useFacetMap((rawData) => ({series1: rawData.map((d) => d.value1),series2: rawData.map((d) => d.value2),series3: rawData.map((d) => d.value3),}),[],[rawDataFacet],createUniformObjectEqualityCheck(shallowArrayEqualityCheck),)
Multi-Region Configuration
tsx
import { useFacetMap, createUniformObjectEqualityCheck, shallowObjectEqualityCheck } from '@react-facet/core'const regionConfigsFacet = useFacetMap((settings) => ({na: { enabled: settings.naEnabled, limit: settings.naLimit },eu: { enabled: settings.euEnabled, limit: settings.euLimit },asia: { enabled: settings.asiaEnabled, limit: settings.asiaLimit },}),[],[settingsFacet],createUniformObjectEqualityCheck(shallowObjectEqualityCheck),)
State Machine Transitions
tsx
import { useFacetMap, createUniformObjectEqualityCheck, shallowArrayEqualityCheck } from '@react-facet/core'const transitionsFacet = useFacetMap((rules) => ({idle: rules.filter((r) => r.from === 'idle').map((r) => r.to),loading: rules.filter((r) => r.from === 'loading').map((r) => r.to),error: rules.filter((r) => r.from === 'error').map((r) => r.to),}),[],[rulesFacet],createUniformObjectEqualityCheck(shallowArrayEqualityCheck),)
See Also
- Equality Checks Overview - Guide to all equality checks
createUniformArrayEqualityCheck
- For arrays with uniform element typescreateObjectWithKeySpecificEqualityCheck
- For objects with different types per propertyshallowObjectEqualityCheck
- For objects with primitive values