-
Notifications
You must be signed in to change notification settings - Fork 141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Textareaの文字数カウンタをonChangeで処理するように修正 #4916
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import React, { | ||
ComponentPropsWithRef, | ||
forwardRef, | ||
startTransition, | ||
useCallback, | ||
useEffect, | ||
useImperativeHandle, | ||
|
@@ -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' | ||
|
@@ -99,6 +101,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props & ElementProps>( | |
onInput, | ||
decorators, | ||
error, | ||
onChange, | ||
...props | ||
}, | ||
ref, | ||
|
@@ -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)) | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
私も同じような理解をしています(存在は知ってたけど使ったことなかった)
可能性としてはありそうですが、setCountの実行回数自体は変わらないはずなのでやはりパフォーマンス懸念は残ってしまうのかも?とか想像しましたが、自信はないです... @hiroki0525 nukosuke-sanお詳しそうなので、このあたりご意見や知見ありますか? 🙇 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
自分も同じ理解です 😇
もしかしたら There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. お二人ともありがとうございます〜!一旦はこちらの実装でいこうと思うんですが、リファクタ可能かもということで認識しておきます...🙇 ! |
||
}, 200), | ||
[], | ||
) | ||
|
||
const handleChange = useCallback( | ||
(event: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
onChange && onChange(event) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @s-sasaki-0529
|
||
maxLetters && debouncedUpdateCount(event.currentTarget.value) | ||
}, | ||
[debouncedUpdateCount, maxLetters, onChange], | ||
) | ||
|
||
const handleInput = useCallback( | ||
(e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
if (!autoResize) { | ||
|
@@ -188,7 +200,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props & ElementProps>( | |
{...props} | ||
{...textareaStyleProps} | ||
aria-describedby={actualMaxLettersId} | ||
onKeyUp={onKeyUp} | ||
onChange={handleChange} | ||
ref={textareaRef} | ||
aria-invalid={error || undefined} | ||
rows={interimRows} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. パッケージを導入せず独自実装した理由は、要件がシンプルだったため、わざわざ外部ライブラリに依存する必要がなく、独自実装で十分そうと判断したためです。 また
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 全然スコープ外の話をするんですけど、この debounce 関数をプロダクトでも使いたい…。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @s-sasaki-0529 実際にtamatebakoに入ったら使われそうですか?:eyes: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OSS なので、PR 投げましょう! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ぶん投げまーす🥋🔥 |
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(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hiroki0525 ガーサス、詳しい...!!! nukosuke-sanの自作ライブラリいずれ入れましょう! 🔥 |
||
func(...args) | ||
}, wait) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同一のstateが利用されていたため、1つのコンポーネントで変更したものが他に影響を与えていたため修正しました。