Skip to content

useTextareaAutosize

Category
Export Size
1.08 kB
Last Changed
5 days ago

Automatically update the height of a textarea depending on the content.

TIP

You may not need this function anymore. Textarea autosizing can now be achieved natively with CSS, see field-sizing: content for more information.

Demo

Usage

Simple example

tsx
import { 
useTextareaAutosize
} from '@reause/core'
const {
input
,
setInput
,
textarea
} =
useTextareaAutosize
()
// <textarea ref={textarea} value={input} onChange={e => setInput(e.target.value)} />

INFO

It's recommended to reset the scrollbar styles for the textarea element to avoid incorrect height values for large amounts of text.

css
textarea {
  -ms-overflow-style: none;
  scrollbar-width: none;
}

textarea::-webkit-scrollbar {
  display: none;
}

With rows attribute

If you need support for the rows attribute on a textarea element, then you should set the styleProp option to minHeight.

tsx
import { 
useTextareaAutosize
} from '@reause/core'
const {
input
,
setInput
,
textarea
} =
useTextareaAutosize
({
styleProp
: 'minHeight' })
// <textarea ref={textarea} value={input} onChange={e => setInput(e.target.value)} rows={3} />

With maxHeight

Use the maxHeight option to cap the textarea height in pixels while keeping autosize behavior.

tsx
import { 
useTextareaAutosize
} from '@reause/core'
const {
input
,
setInput
,
textarea
} =
useTextareaAutosize
({
maxHeight
: 180,
styleProp
: 'minHeight',
}) // <textarea ref={textarea} value={input} onChange={e => setInput(e.target.value)} rows={3} />

Return Values

useTextareaAutosize returns the object { input, setInput, textarea, triggerResize }:

PropertyTypeDescription
inputstringCurrent textarea content — the input option when provided, otherwise the hook-owned state.
setInputDispatch<SetStateAction<string>>Updates the hook-owned content (upstream: writing input.value). Has no effect on the resize while an input option is provided.
textareaRefObject<HTMLTextAreaElement | null>Bind it to the <textarea> with ref={textarea} when the element option is omitted (upstream: the textarea ref).
triggerResize() => voidManually trigger a textarea resize (upstream: triggerResize).

React divergence from upstream

Upstream returns { textarea: Ref<HTMLTextAreaElement | undefined | null>, input: Ref<string>, triggerResize }, so consumers read and write input.value. This port mirrors that object and pairs the writable content with a setter — { input, setInput, textarea, triggerResize }.

The element and styleTarget options accept a React ref (RefObject holding the element), and the textarea is resolved at commit time, so an element attached after mount (conditional or async render) still triggers the resize and the ResizeObserver. The watch values are compared with the shared structural deepEqual (functions by reference; Map / Set / Date / RegExp by contents) instead of a JSON.stringify key, so non-serializable values re-trigger the resize. Upstream's two mount watches are merged into one commit-time effect, so the mount resize runs once instead of twice.

Type Declarations

ts
export interface UseTextareaAutosizeOptions {
    window?: Window;
    element?: RefObject<HTMLTextAreaElement | null>;
    input?: string;
    maxHeight?: number;
    watch?: unknown[];
    onResize?: () => void;
    styleTarget?: RefObject<HTMLElement | null>;
    styleProp?: 'height' | 'minHeight';
}

export interface UseTextareaAutosizeReturn {
    readonly input: string;
    readonly setInput: Dispatch<SetStateAction<string>>;
    readonly textarea: RefObject<HTMLTextAreaElement | null>;
    readonly triggerResize: () => void;
}

export function useTextareaAutosize(options?: UseTextareaAutosizeOptions): UseTextareaAutosizeReturn

Source

Source · Demo · VueUse

Contributors

hairyf

Changelog

v0.1.0 on
f8fc2 - fix(core): resolve useTextareaAutosize audit findings (#655)

Released under the MIT License. v0.1.8