From 199e222c742dfeb866d3cbdbf17cbcfe00911be2 Mon Sep 17 00:00:00 2001 From: Victor Trinh Date: Wed, 18 Sep 2024 14:41:23 -0400 Subject: [PATCH] [DS-276] Resize TextArea when value changes with a debounce --- .changeset/seven-rice-hang.md | 5 +++++ packages/Textarea/src/Textarea.tsx | 4 +++- packages/Textarea/src/hooks/useDebounce.ts | 17 +++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 .changeset/seven-rice-hang.md create mode 100644 packages/Textarea/src/hooks/useDebounce.ts diff --git a/.changeset/seven-rice-hang.md b/.changeset/seven-rice-hang.md new file mode 100644 index 00000000..070cc565 --- /dev/null +++ b/.changeset/seven-rice-hang.md @@ -0,0 +1,5 @@ +--- +"@igloo-ui/textarea": patch +--- + +Resize textarea on value change with a 300ms debounce diff --git a/packages/Textarea/src/Textarea.tsx b/packages/Textarea/src/Textarea.tsx index 28149c16..5b4c1caf 100644 --- a/packages/Textarea/src/Textarea.tsx +++ b/packages/Textarea/src/Textarea.tsx @@ -7,6 +7,7 @@ import useCharLength from "./hooks/useCharLength"; import useTruncateValue from "./hooks/useTruncateValue"; import "./textarea.scss"; +import { useDebounce } from "./hooks/useDebounce"; export interface TextareaProps extends React.ComponentPropsWithRef<"textarea"> { /** True if the textarea should allow new lines with Enter. */ @@ -58,6 +59,7 @@ const Textarea: React.FunctionComponent = React.forwardRef( const textareaRef = React.useRef(null); const mergedTextareaRef = mergeRefs(textareaRef, ref); const [currentValue, setCurrentValue] = React.useState(value ?? ""); + const debounceCurrentValue = useDebounce(currentValue, 300); const textareaMaxLength = maxLength ?? 0; const charLength = useCharLength(currentValue, textareaMaxLength); const displayCharIndicator = @@ -106,7 +108,7 @@ const Textarea: React.FunctionComponent = React.forwardRef( autosize(textareaRef.current); autosize.update(textareaRef.current); } - }, [textareaRef, isAutoResize]); + }, [textareaRef, isAutoResize, debounceCurrentValue]); React.useEffect(() => { const newValue = truncateValue(value?.toString() ?? "", maxLength); diff --git a/packages/Textarea/src/hooks/useDebounce.ts b/packages/Textarea/src/hooks/useDebounce.ts new file mode 100644 index 00000000..3040a2ee --- /dev/null +++ b/packages/Textarea/src/hooks/useDebounce.ts @@ -0,0 +1,17 @@ +import { useEffect, useState } from "react"; + +export function useDebounce(value: T, delay: number): T { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + return () => { + clearTimeout(handler); + }; + }, [value, delay]); + + return debouncedValue; +}