Skip to content

Commit

Permalink
fix: Textareaの文字数カウンタをonChangeで処理するように修正 (#4916)
Browse files Browse the repository at this point in the history
  • Loading branch information
atzzCokeK authored Sep 13, 2024
1 parent 51dbdb8 commit a054e07
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 18 deletions.
18 changes: 9 additions & 9 deletions packages/smarthr-ui/src/components/Textarea/Textarea.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export default {
}

const Template: StoryFn = () => {
const [value, setValue] = useState('message👌')
const onChangeValue = (e: React.ChangeEvent<HTMLTextAreaElement>) =>
setValue(e.currentTarget.value)
const [value1, setValue1] = useState('message👌')
const [value2, setValue2] = useState('message👌')
const [value3, setValue3] = useState('message👌')
return (
<ListStack>
<li>
Expand Down Expand Up @@ -58,8 +58,8 @@ const Template: StoryFn = () => {
<Textarea
name="max_length_with_value"
maxLetters={140}
value={value}
onChange={onChangeValue}
value={value1}
onChange={(e) => setValue1(e.target.value)}
/>
</FormControl>
</li>
Expand All @@ -68,8 +68,8 @@ const Template: StoryFn = () => {
<Textarea
name="max_length_with_value_over"
maxLetters={4}
value={value}
onChange={onChangeValue}
value={value2}
onChange={(e) => setValue2(e.target.value)}
/>
</FormControl>
</li>
Expand All @@ -78,8 +78,8 @@ const Template: StoryFn = () => {
<Textarea
name="max_length_with_value_and_decorators"
maxLetters={140}
value={value}
onChange={onChangeValue}
value={value3}
onChange={(e) => setValue3(e.target.value)}
decorators={{
beforeMaxLettersCount: (txt) => `entry limit(${txt})`,
afterMaxLettersCount: (txt) => ` characters(${txt})`,
Expand Down
30 changes: 21 additions & 9 deletions packages/smarthr-ui/src/components/Textarea/Textarea.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {
ComponentPropsWithRef,
forwardRef,
startTransition,
useCallback,
useEffect,
useImperativeHandle,
Expand All @@ -12,6 +13,7 @@ import { tv } from 'tailwind-variants'

import { useId } from '../../hooks/useId'
import { useTheme } from '../../hooks/useTailwindTheme'
import { debounce } from '../../libs/debounce'
import { defaultHtmlFontSize } from '../../themes/createFontSize'

import type { DecoratorsType } from '../../types'
Expand Down Expand Up @@ -99,6 +101,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props & ElementProps>(
onInput,
decorators,
error,
onChange,
...props
},
ref,
Expand Down Expand Up @@ -135,15 +138,24 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props & ElementProps>(
}
}, [autoFocus])

const onKeyUp = useMemo(
() =>
maxLetters
? (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
setCount(getStringLength(event.currentTarget.value))
}
: undefined,
[maxLetters],
// eslint-disable-next-line react-hooks/exhaustive-deps
const debouncedUpdateCount = useCallback(
debounce((value) => {
startTransition(() => {
setCount(getStringLength(value))
})
}, 200),
[],
)

const handleChange = useCallback(
(event: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange && onChange(event)
maxLetters && debouncedUpdateCount(event.currentTarget.value)
},
[debouncedUpdateCount, maxLetters, onChange],
)

const handleInput = useCallback(
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
if (!autoResize) {
Expand Down Expand Up @@ -189,7 +201,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props & ElementProps>(
{...textareaStyleProps}
data-smarthr-ui-input="true"
aria-describedby={actualMaxLettersId}
onKeyUp={onKeyUp}
onChange={handleChange}
ref={textareaRef}
aria-invalid={error || undefined}
rows={interimRows}
Expand Down
26 changes: 26 additions & 0 deletions packages/smarthr-ui/src/libs/debounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* 関数の呼び出しを指定された待機時間 (wait) だけ遅延させるデバウンス関数。
* 直前に同じ関数が呼び出された場合、タイマーをリセットして再び遅延させます。
*
* @param {T} func - 実行する関数
* @param {number} wait - デバウンスの待機時間(ミリ秒)
* @returns {(...args: Parameters<T>) => void} デバウンスされた関数
*
* @example
* const debouncedFunction = debounce(() => console.log('Called!'), 200);
*/
export const debounce = <T extends (...args: any[]) => void>(
func: T,
wait: number,
): ((...args: Parameters<T>) => void) => {
let timeoutId: ReturnType<typeof setTimeout> | null = null

return function (...args: Parameters<T>) {
if (timeoutId !== null) {
clearTimeout(timeoutId)
}
timeoutId = setTimeout(() => {
func(...args)
}, wait)
}
}

0 comments on commit a054e07

Please sign in to comment.