5
5
unstable_debounce as debounce ,
6
6
unstable_useForkRef as useForkRef ,
7
7
unstable_useEnhancedEffect as useEnhancedEffect ,
8
+ unstable_useEventCallback as useEventCallback ,
8
9
unstable_ownerWindow as ownerWindow ,
9
10
} from '@mui/utils' ;
10
11
import { TextareaAutosizeProps } from './TextareaAutosize.types' ;
@@ -129,6 +130,19 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(
129
130
return { outerHeightStyle, overflowing } ;
130
131
} , [ maxRows , minRows , props . placeholder ] ) ;
131
132
133
+ const didHeightChange = useEventCallback ( ( ) => {
134
+ const textarea = textareaRef . current ;
135
+ const textareaStyles = calculateTextareaStyles ( ) ;
136
+
137
+ if ( ! textarea || ! textareaStyles || isEmpty ( textareaStyles ) ) {
138
+ return false ;
139
+ }
140
+
141
+ const outerHeightStyle = textareaStyles . outerHeightStyle ;
142
+
143
+ return heightRef . current != null && heightRef . current !== outerHeightStyle ;
144
+ } ) ;
145
+
132
146
const syncHeight = React . useCallback ( ( ) => {
133
147
const textarea = textareaRef . current ;
134
148
const textareaStyles = calculateTextareaStyles ( ) ;
@@ -148,7 +162,7 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(
148
162
const frameRef = React . useRef ( - 1 ) ;
149
163
150
164
useEnhancedEffect ( ( ) => {
151
- const debounceHandleResize = debounce ( ( ) => syncHeight ( ) ) ;
165
+ const debouncedHandleResize = debounce ( syncHeight ) ;
152
166
const textarea = textareaRef ?. current ;
153
167
154
168
if ( ! textarea ) {
@@ -157,34 +171,36 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(
157
171
158
172
const containerWindow = ownerWindow ( textarea ) ;
159
173
160
- containerWindow . addEventListener ( 'resize' , debounceHandleResize ) ;
174
+ containerWindow . addEventListener ( 'resize' , debouncedHandleResize ) ;
161
175
162
176
let resizeObserver : ResizeObserver ;
163
177
164
178
if ( typeof ResizeObserver !== 'undefined' ) {
165
179
resizeObserver = new ResizeObserver ( ( ) => {
166
- // avoid "ResizeObserver loop completed with undelivered notifications" error
167
- // by temporarily unobserving the textarea element while manipulating the height
168
- // and reobserving one frame later
169
- resizeObserver . unobserve ( textarea ) ;
170
- cancelAnimationFrame ( frameRef . current ) ;
171
- syncHeight ( ) ;
172
- frameRef . current = requestAnimationFrame ( ( ) => {
173
- resizeObserver . observe ( textarea ) ;
174
- } ) ;
180
+ if ( didHeightChange ( ) ) {
181
+ // avoid "ResizeObserver loop completed with undelivered notifications" error
182
+ // by temporarily unobserving the textarea element while manipulating the height
183
+ // and reobserving one frame later
184
+ resizeObserver . unobserve ( textarea ) ;
185
+ cancelAnimationFrame ( frameRef . current ) ;
186
+ syncHeight ( ) ;
187
+ frameRef . current = requestAnimationFrame ( ( ) => {
188
+ resizeObserver . observe ( textarea ) ;
189
+ } ) ;
190
+ }
175
191
} ) ;
176
192
resizeObserver . observe ( textarea ) ;
177
193
}
178
194
179
195
return ( ) => {
180
- debounceHandleResize . clear ( ) ;
196
+ debouncedHandleResize . clear ( ) ;
181
197
cancelAnimationFrame ( frameRef . current ) ;
182
- containerWindow . removeEventListener ( 'resize' , debounceHandleResize ) ;
198
+ containerWindow . removeEventListener ( 'resize' , debouncedHandleResize ) ;
183
199
if ( resizeObserver ) {
184
200
resizeObserver . disconnect ( ) ;
185
201
}
186
202
} ;
187
- } , [ calculateTextareaStyles , syncHeight ] ) ;
203
+ } , [ calculateTextareaStyles , syncHeight , didHeightChange ] ) ;
188
204
189
205
useEnhancedEffect ( ( ) => {
190
206
syncHeight ( ) ;
0 commit comments