@@ -96,6 +96,122 @@ describe('withErrorBoundary', () => {
9696 const Component = withErrorBoundary ( ( ) => < h1 > Hello World</ h1 > , { fallback : < h1 > fallback</ h1 > } ) ;
9797 expect ( Component . displayName ) . toBe ( `errorBoundary(${ UNKNOWN_COMPONENT } )` ) ;
9898 } ) ;
99+
100+ it ( 'does not rerender when props are identical' , ( ) => {
101+ let renderCount = 0 ;
102+ const TestComponent = ( { title } : { title : string } ) => {
103+ renderCount ++ ;
104+ return < h1 > { title } </ h1 > ;
105+ } ;
106+
107+ const WrappedComponent = withErrorBoundary ( TestComponent , { fallback : < h1 > fallback</ h1 > } ) ;
108+ const { rerender } = render ( < WrappedComponent title = "test" /> ) ;
109+
110+ expect ( renderCount ) . toBe ( 1 ) ;
111+
112+ // Rerender with identical props - should not cause TestComponent to rerender
113+ rerender ( < WrappedComponent title = "test" /> ) ;
114+ expect ( renderCount ) . toBe ( 1 ) ;
115+
116+ // Rerender with different props - should cause TestComponent to rerender
117+ rerender ( < WrappedComponent title = "different" /> ) ;
118+ expect ( renderCount ) . toBe ( 2 ) ;
119+ } ) ;
120+
121+ it ( 'does not rerender when complex props are identical' , ( ) => {
122+ let renderCount = 0 ;
123+ const TestComponent = ( { data } : { data : { id : number ; name : string } } ) => {
124+ renderCount ++ ;
125+ return < h1 > { data . name } </ h1 > ;
126+ } ;
127+
128+ const WrappedComponent = withErrorBoundary ( TestComponent , { fallback : < h1 > fallback</ h1 > } ) ;
129+ const props = { data : { id : 1 , name : 'test' } } ;
130+ const { rerender } = render ( < WrappedComponent { ...props } /> ) ;
131+
132+ expect ( renderCount ) . toBe ( 1 ) ;
133+
134+ // Rerender with same object reference - should not cause TestComponent to rerender
135+ rerender ( < WrappedComponent { ...props } /> ) ;
136+ expect ( renderCount ) . toBe ( 1 ) ;
137+
138+ // Rerender with different object but same values - should cause rerender
139+ rerender ( < WrappedComponent data = { { id : 1 , name : 'test' } } /> ) ;
140+ expect ( renderCount ) . toBe ( 2 ) ;
141+
142+ // Rerender with different values - should cause rerender
143+ rerender ( < WrappedComponent data = { { id : 2 , name : 'different' } } /> ) ;
144+ expect ( renderCount ) . toBe ( 3 ) ;
145+ } ) ;
146+
147+ it ( 'does not rerender when errorBoundaryOptions are the same' , ( ) => {
148+ let renderCount = 0 ;
149+ const TestComponent = ( { title } : { title : string } ) => {
150+ renderCount ++ ;
151+ return < h1 > { title } </ h1 > ;
152+ } ;
153+
154+ const errorBoundaryOptions = { fallback : < h1 > fallback</ h1 > } ;
155+ const WrappedComponent = withErrorBoundary ( TestComponent , errorBoundaryOptions ) ;
156+ const { rerender } = render ( < WrappedComponent title = "test" /> ) ;
157+
158+ expect ( renderCount ) . toBe ( 1 ) ;
159+
160+ // Rerender with identical props - should not cause TestComponent to rerender
161+ rerender ( < WrappedComponent title = "test" /> ) ;
162+ expect ( renderCount ) . toBe ( 1 ) ;
163+ } ) ;
164+
165+ it ( 'preserves function component behavior with React.memo' , ( ) => {
166+ const TestComponent = ( { title } : { title : string } ) => < h1 > { title } </ h1 > ;
167+ const WrappedComponent = withErrorBoundary ( TestComponent , { fallback : < h1 > fallback</ h1 > } ) ;
168+
169+ expect ( WrappedComponent ) . toBeDefined ( ) ;
170+ expect ( typeof WrappedComponent ) . toBe ( 'object' ) ;
171+ expect ( WrappedComponent . displayName ) . toBe ( 'errorBoundary(TestComponent)' ) ;
172+
173+ const { container } = render ( < WrappedComponent title = "test" /> ) ;
174+ expect ( container . innerHTML ) . toContain ( 'test' ) ;
175+ } ) ;
176+
177+ it ( 'does not rerender parent component unnecessarily' , ( ) => {
178+ let parentRenderCount = 0 ;
179+ let childRenderCount = 0 ;
180+
181+ const ChildComponent = ( { value } : { value : number } ) => {
182+ childRenderCount ++ ;
183+ return < div > Child: { value } </ div > ;
184+ } ;
185+
186+ const WrappedChild = withErrorBoundary ( ChildComponent , { fallback : < div > Error</ div > } ) ;
187+
188+ const ParentComponent = ( { childValue, otherProp } : { childValue : number ; otherProp : string } ) => {
189+ parentRenderCount ++ ;
190+ return (
191+ < div >
192+ < div > Parent: { otherProp } </ div >
193+ < WrappedChild value = { childValue } />
194+ </ div >
195+ ) ;
196+ } ;
197+
198+ const { rerender } = render ( < ParentComponent childValue = { 1 } otherProp = "test" /> ) ;
199+
200+ expect ( parentRenderCount ) . toBe ( 1 ) ;
201+ expect ( childRenderCount ) . toBe ( 1 ) ;
202+
203+ // Change otherProp but keep childValue the same
204+ rerender ( < ParentComponent childValue = { 1 } otherProp = "changed" /> ) ;
205+
206+ expect ( parentRenderCount ) . toBe ( 2 ) ; // Parent should rerender
207+ expect ( childRenderCount ) . toBe ( 1 ) ; // Child should NOT rerender due to memo
208+
209+ // Change childValue
210+ rerender ( < ParentComponent childValue = { 2 } otherProp = "changed" /> ) ;
211+
212+ expect ( parentRenderCount ) . toBe ( 3 ) ; // Parent should rerender
213+ expect ( childRenderCount ) . toBe ( 2 ) ; // Child should rerender due to changed props
214+ } ) ;
99215} ) ;
100216
101217describe ( 'ErrorBoundary' , ( ) => {
0 commit comments