@@ -108,6 +108,10 @@ const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
108108 const [ isOverLimit , setIsOverLimit ] = useState < boolean > ( false )
109109 const [ screenReaderMessage , setScreenReaderMessage ] = useState < string > ( '' )
110110 const characterCounterRef = useRef < CharacterCounter | null > ( null )
111+ const lastCountedLengthRef = useRef < number | null > ( null )
112+ const lastCharacterCountRef = useRef < string > ( '' )
113+ const lastIsOverLimitRef = useRef < boolean > ( false )
114+ const lastScreenReaderMessageRef = useRef < string > ( '' )
111115
112116 // this class is necessary to style FilterSearch, plz no touchy!
113117 const wrapperClasses = clsx ( className , 'TextInput-wrapper' )
@@ -157,17 +161,33 @@ const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
157161 if ( characterLimit ) {
158162 characterCounterRef . current = new CharacterCounter ( {
159163 onCountUpdate : ( count , overLimit , message ) => {
160- setCharacterCount ( message )
161- setIsOverLimit ( overLimit )
164+ if ( message !== lastCharacterCountRef . current ) {
165+ lastCharacterCountRef . current = message
166+ setCharacterCount ( message )
167+ }
168+
169+ if ( overLimit !== lastIsOverLimitRef . current ) {
170+ lastIsOverLimitRef . current = overLimit
171+ setIsOverLimit ( overLimit )
172+ }
162173 } ,
163174 onScreenReaderAnnounce : message => {
164- setScreenReaderMessage ( message )
175+ if ( message !== lastScreenReaderMessageRef . current ) {
176+ lastScreenReaderMessageRef . current = message
177+ setScreenReaderMessage ( message )
178+ }
165179 } ,
166180 } )
167181
182+ lastCountedLengthRef . current = null
183+
168184 return ( ) => {
169185 characterCounterRef . current ?. cleanup ( )
170186 characterCounterRef . current = null
187+ lastCountedLengthRef . current = null
188+ lastCharacterCountRef . current = ''
189+ lastIsOverLimitRef . current = false
190+ lastScreenReaderMessageRef . current = ''
171191 }
172192 }
173193 } , [ characterLimit ] )
@@ -177,15 +197,25 @@ const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
177197 if ( characterLimit && characterCounterRef . current ) {
178198 const currentValue =
179199 value !== undefined ? String ( value ) : defaultValue !== undefined ? String ( defaultValue ) : ''
180- characterCounterRef . current . updateCharacterCount ( currentValue . length , characterLimit )
200+ const currentLength = currentValue . length
201+
202+ if ( currentLength !== lastCountedLengthRef . current ) {
203+ lastCountedLengthRef . current = currentLength
204+ characterCounterRef . current . updateCharacterCount ( currentLength , characterLimit )
205+ }
181206 }
182207 } , [ value , defaultValue , characterLimit ] )
183208
184209 // Handle input change with character counter
185210 const handleInputChange = useCallback (
186211 ( e : React . ChangeEvent < HTMLInputElement > ) => {
187212 if ( characterLimit && characterCounterRef . current ) {
188- characterCounterRef . current . updateCharacterCount ( e . target . value . length , characterLimit )
213+ const currentLength = e . target . value . length
214+
215+ if ( currentLength !== lastCountedLengthRef . current ) {
216+ lastCountedLengthRef . current = currentLength
217+ characterCounterRef . current . updateCharacterCount ( currentLength , characterLimit )
218+ }
189219 }
190220 onChange ?.( e )
191221 } ,
0 commit comments