React Textarea Autosize
react-textarea-autosize is a React component that serves as a high-performance, lightweight (approx. 1.3KB minified & gzipped) drop-in replacement for the native `<textarea>` HTML element, automatically adjusting its height to fit its content. Inspired by the popular jQuery Autosize plugin, it provides a seamless user experience for input fields that need to expand dynamically. The package is currently at version 8.5.9 and maintains an active release cadence with frequent patch updates to address bugs and improve compatibility. Key differentiators include its small size, broad React compatibility (supporting React 16.8.0 through 19.0.0), and specific features like `minRows`, `maxRows`, and an `onHeightChange` callback. Recent enhancements have focused on improving module resolution for modern JavaScript runtimes such as Vercel Edge and Cloudflare Workers, resolving race conditions, and bolstering Node.js ESM support.
Common errors
-
Cannot read properties of null (reading 'style') or similar runtime errors during component unmount.
cause A race condition where an internal `requestAnimationFrame` callback tries to access a DOM element that has already been removed from the document.fixUpgrade to `react-textarea-autosize@8.5.8` or later to include the fix for this race condition. -
Textarea height does not change when content is added or removed, or after form reset.
cause Conflicting CSS styles (especially `display` properties) overriding the internal sizing mechanism, or an issue where the component didn't correctly react to form reset events.fixVerify that no custom CSS is overriding essential layout properties on the `TextareaAutosize` component. For form reset issues, ensure you are using `react-textarea-autosize@8.5.7` or newer, which fixed this specific problem. -
TypeError: Cannot read properties of undefined (reading 'focus') or similar when using `ref` in testing environments.
cause `react-test-renderer` (and JSDOM by default) does not provide a concrete DOM node for `ref` callbacks without explicit configuration, causing refs to be `null` or `undefined`.fixWhen using `react-test-renderer`, pass the `createNodeMock` option to `renderer.create` to mock DOM elements for refs, e.g., `renderer.create(<TextareaAutosize />, { createNodeMock: () => document.createElement('textarea') })`.
Warnings
- gotcha Older versions (prior to v8.5.0) might exhibit inconsistent module resolution behavior, particularly for Node.js ESM environments, potentially leading to incorrect imports or bundling issues.
- gotcha When testing `TextareaAutosize` with `react-test-renderer` or JSDOM-based environments, direct refs to the underlying DOM element might not work as expected because `createNodeMock` is not called by default for all components.
- gotcha The internal sizing mechanism relies on a hidden textarea with `display: block`. Custom CSS that overrides this property or other critical layout styles can prevent the component from resizing correctly.
- gotcha Prior to v8.5.8, a race condition could occur where an internal `requestAnimationFrame` callback would attempt to execute after the textarea component had already been unmounted, leading to errors during component lifecycle.
Install
-
npm install react-textarea-autosize -
yarn add react-textarea-autosize -
pnpm add react-textarea-autosize
Imports
- TextareaAutosize
import TextareaAutosize from 'react-textarea-autosize';
- TextareaAutosize
const { TextareaAutosize } = require('react-textarea-autosize');const TextareaAutosize = require('react-textarea-autosize').default; - TextareaAutosizeProps
import type { TextareaAutosizeProps } from 'react-textarea-autosize';
Quickstart
import React from 'react';
import { createRoot } from 'react-dom/client';
import TextareaAutosize from 'react-textarea-autosize';
const App = () => {
const [value, setValue] = React.useState('Hello, world!\nThis is an autosizing textarea.\nTry typing more to see it grow.');
return (
<div style={{ padding: '20px', maxWidth: '400px', margin: 'auto' }}>
<h1>Autosizing Textarea Demo</h1>
<TextareaAutosize
value={value}
onChange={(e) => setValue(e.target.value)}
minRows={3}
maxRows={10}
placeholder="Type something here..."
style={{
width: '100%',
padding: '8px',
fontSize: '16px',
lineHeight: '1.5',
border: '1px solid #ccc',
borderRadius: '4px',
boxSizing: 'border-box', // Crucial for correct sizing
resize: 'none', // Disable native resize
}}
onHeightChange={(height, { rowHeight }) => {
console.log(`Textarea height changed to: ${height}px (rowHeight: ${rowHeight}px)`);
}}
/>
<p style={{ marginTop: '20px' }}>Current value: {value}</p>
</div>
);
};
const container = document.getElementById('root');
if (container) {
const root = createRoot(container);
root.render(<App />);
} else {
console.error("Root element not found.");
}