Fastest deep equal comparison for React with optimizations for React elements and circular reference handling
npx @tessl/cli install tessl/npm-react-fast-compare@3.2.00
# React Fast Compare
1
2
React Fast Compare provides the fastest deep equal comparison for React applications, with optimizations for React elements and built-in circular reference handling. It offers a single unified entry point that handles React-specific circular references like React elements, includes try/catch guardrails for stack overflows, and supports all JavaScript data types.
3
4
## Package Information
5
6
- **Package Name**: react-fast-compare
7
- **Package Type**: npm
8
- **Language**: JavaScript (with TypeScript definitions)
9
- **Installation**: `npm install react-fast-compare` or `yarn add react-fast-compare`
10
11
## Core Imports
12
13
```javascript
14
const isEqual = require('react-fast-compare');
15
```
16
17
For ES modules/TypeScript:
18
19
```typescript
20
import isEqual = require('react-fast-compare');
21
```
22
23
## Basic Usage
24
25
```javascript
26
const isEqual = require('react-fast-compare');
27
28
// General deep comparison
29
console.log(isEqual({ foo: 'bar' }, { foo: 'bar' })); // true
30
console.log(isEqual([1, 2, 3], [1, 2, 3])); // true
31
32
// React.memo usage
33
const MemoComponent = React.memo(ExpensiveComponent, isEqual);
34
35
// shouldComponentUpdate usage
36
class Component extends React.Component {
37
shouldComponentUpdate(nextProps) {
38
return !isEqual(this.props, nextProps);
39
}
40
}
41
42
// React-Redux useSelector usage
43
const value = useSelector(selector, isEqual);
44
```
45
46
## Capabilities
47
48
### Deep Equality Comparison
49
50
Performs deep equality comparison optimized for React applications with circular reference handling.
51
52
```typescript { .api }
53
/**
54
* Compare two values for deep equality with React-specific optimizations
55
* @param a - First value to compare
56
* @param b - Second value to compare
57
* @returns true if values are deeply equal, false otherwise
58
*/
59
function isEqual<A = any, B = any>(a: A, b: B): boolean;
60
```
61
62
**Supported Data Types:**
63
- **Primitives**: string, number, boolean, null, undefined, symbol, bigint
64
- **Objects**: Plain objects, arrays
65
- **Built-in Objects**: Date, RegExp, Map, Set, ArrayBuffer views (typed arrays)
66
- **React Elements**: Special handling for React/Preact elements with circular reference avoidance
67
- **DOM Elements**: Special handling for DOM Element instances
68
69
**React-Specific Features:**
70
- **Circular Reference Handling**: Automatically skips `_owner`, `__v`, `__o` properties in React/Preact elements to avoid infinite loops
71
- **Element Comparison**: DOM Element instances always return false (different elements are never equal)
72
- **Stack Overflow Protection**: Catches stack overflow errors from undetected circular references and returns false with console warning
73
74
**Error Handling:**
75
- **Circular References**: Returns `false` and logs "react-fast-compare cannot handle circular refs" warning
76
- **Stack Overflow**: Detects stack/recursion errors and safely returns `false`
77
- **Other Errors**: Re-throws unexpected errors for proper debugging
78
79
**Performance Characteristics:**
80
- **ES5 Compatible**: Works in IE9+ and Node.js 0.10+
81
- **Bundle Size**: 656 bytes minified+gzipped
82
- **Speed**: Comparable to fast-deep-equal for general data, optimized for React use cases
83
84
**Usage Examples:**
85
86
```javascript
87
// Basic object comparison
88
isEqual({ name: 'Alice', age: 25 }, { name: 'Alice', age: 25 }); // true
89
isEqual({ name: 'Alice' }, { name: 'Bob' }); // false
90
91
// Array comparison
92
isEqual([1, 2, [3, 4]], [1, 2, [3, 4]]); // true
93
isEqual([1, 2, 3], [1, 2, 4]); // false
94
95
// Date comparison
96
isEqual(new Date('2023-01-01'), new Date('2023-01-01')); // true
97
isEqual(new Date('2023-01-01'), new Date('2023-01-02')); // false
98
99
// RegExp comparison
100
isEqual(/abc/gi, /abc/gi); // true
101
isEqual(/abc/g, /abc/i); // false
102
103
// Map comparison
104
const map1 = new Map([['a', 1], ['b', 2]]);
105
const map2 = new Map([['a', 1], ['b', 2]]);
106
isEqual(map1, map2); // true
107
108
// Set comparison
109
const set1 = new Set([1, 2, 3]);
110
const set2 = new Set([1, 2, 3]);
111
isEqual(set1, set2); // true
112
113
// React element comparison (skips circular references)
114
const element1 = React.createElement('div', { id: 'test' }, 'Hello');
115
const element2 = React.createElement('div', { id: 'test' }, 'Hello');
116
isEqual(element1, element2); // true (ignores _owner and other circular props)
117
118
// Typed array comparison
119
const arr1 = new Uint8Array([1, 2, 3]);
120
const arr2 = new Uint8Array([1, 2, 3]);
121
isEqual(arr1, arr2); // true
122
```
123
124
**Integration Examples:**
125
126
```typescript
127
// React.memo with custom comparison
128
interface Props {
129
data: ComplexObject;
130
config: ConfigObject;
131
}
132
133
const OptimizedComponent = React.memo<Props>(({ data, config }) => {
134
// Expensive component logic
135
return <div>{/* Complex UI */}</div>;
136
}, isEqual);
137
138
// Class component shouldComponentUpdate
139
class ExpensiveList extends React.Component<ListProps> {
140
shouldComponentUpdate(nextProps: ListProps) {
141
// Only re-render if props actually changed
142
return !isEqual(this.props, nextProps);
143
}
144
145
render() {
146
return (
147
<ul>
148
{this.props.items.map(item =>
149
<li key={item.id}>{item.name}</li>
150
)}
151
</ul>
152
);
153
}
154
}
155
156
// React-Redux useSelector with equality check
157
const selectUserData = (state: RootState) => ({
158
user: state.user,
159
preferences: state.preferences,
160
settings: state.settings
161
});
162
163
function UserProfile() {
164
// Prevents unnecessary re-renders when reference changes but content is same
165
const userData = useSelector(selectUserData, isEqual);
166
167
return <div>{userData.user.name}</div>;
168
}
169
```