Skip to content

Commit

Permalink
Fixed an issue with resize not happening after form being reset (#409)
Browse files Browse the repository at this point in the history
* Fixed an issue with resize not happening after form being reset

* improve the fix

* Create friendly-masks-rescue.md

* non-null assertion
  • Loading branch information
Andarist authored Jan 9, 2025
1 parent ae64b9f commit 8c47e31
Show file tree
Hide file tree
Showing 9 changed files with 4,555 additions and 8,982 deletions.
5 changes: 5 additions & 0 deletions .changeset/friendly-masks-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-textarea-autosize": patch
---

Fixed an issue with resize not happening after the containing form being reset
2 changes: 1 addition & 1 deletion example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@
<body>
<h1>React &lt;TextareaAutosize /&gt; component</h1>
<div id="main"></div>
<script src="./index.tsx"></script>
<script type="module" src="./index.tsx"></script>
</body>
36 changes: 34 additions & 2 deletions example/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { createRoot } from 'react-dom/client';
import TextareaAutosize from '../src';

const range = (n: number): number[] => Array.from({ length: n }, (_, i) => i);
Expand Down Expand Up @@ -202,6 +202,36 @@ const WithCustomFont = () => {
);
};

const WithFormReset = () => {
const ref = React.useRef<HTMLFormElement>(null);
return (
<div>
<h2>{'Resettable form.'}</h2>
<div>{'Resizes once the form gets reset.'}</div>
<form ref={ref}>
<TextareaAutosize />
<input type="reset" />
</form>
</div>
);
};

const WithManualFormReset = () => {
const ref = React.useRef<HTMLFormElement>(null);
return (
<div>
<h2>{'Resettable form via manual reset call.'}</h2>
<div>{'Resizes once the form gets reset.'}</div>
<form ref={ref}>
<TextareaAutosize />
<button type="button" onClick={() => ref.current?.reset()}>
{'Reset'}
</button>
</form>
</div>
);
};

const Demo = () => {
return (
<div>
Expand All @@ -215,8 +245,10 @@ const Demo = () => {
<OnHeightChangeCallback />
<MultipleTextareas />
<WithCustomFont />
<WithFormReset />
<WithManualFormReset />
</div>
);
};

ReactDOM.render(<Demo />, document.getElementById('main'));
createRoot(document.getElementById('main')!).render(<Demo />);
5 changes: 3 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "parcel ./index.html --open",
"build": "parcel build ./index.html --dist-dir ./dist --public-url ."
"dev": "vite",
"build": "vite build"
}
}
6 changes: 6 additions & 0 deletions example/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
plugins: [react()],
});
16 changes: 7 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,10 @@
"Mateusz Burzyński <mateuszburzynski@gmail.com> (/~https://github.com/Andarist)"
],
"scripts": {
"prebuild": "npm run clean",
"build": "preconstruct build",
"docs:dev": "npm run dev --prefix example",
"docs:build": "npm run build --prefix example",
"docs:publish": "npm run docs:build && cd ./example/dist && git init && git commit --allow-empty -m 'update docs' && git checkout -b gh-pages && touch .nojekyll && git add . && git commit -am 'update docs' && git push git@github.com:Andarist/react-textarea-autosize gh-pages --force",
"clean": "rimraf dist",
"lint": "eslint --ext .js,.ts,.tsx src",
"prepare": "npm run build",
"changeset": "changeset",
Expand Down Expand Up @@ -110,10 +108,11 @@
"@preconstruct/cli": "^2.8.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^10.4.9",
"@types/react": "^16.14.35",
"@types/react-dom": "^16.9.17",
"@types/react": "^18",
"@types/react-dom": "^18",
"@typescript-eslint/eslint-plugin": "^5.51.0",
"@typescript-eslint/parser": "^5.51.0",
"@vitejs/plugin-react": "^4.3.4",
"babel-eslint": "11.0.0-beta.2",
"bytes": "^3.1.0",
"cross-env": "^7.0.2",
Expand All @@ -125,13 +124,12 @@
"jest": "^29.4.2",
"jest-environment-jsdom": "^29.4.2",
"lint-staged": "^10.2.8",
"parcel": "2.0.0-nightly.454",
"prettier": "^2.8.4",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rimraf": "^3.0.2",
"terser": "^4.7.0",
"typescript": "^5.1.3"
"typescript": "^5.1.3",
"vite": "^6.0.7"
},
"engines": {
"node": ">=10"
Expand Down
13 changes: 11 additions & 2 deletions src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,26 @@ function useListener<
const latestListener = useLatest(listener);
React.useLayoutEffect(() => {
const handler: typeof listener = (ev) => latestListener.current(ev);

// might happen if document.fonts is not defined, for instance
if (!target) {
return;
}

target.addEventListener(type, handler);
return () => target.removeEventListener(type, handler);
}, []);
}

export const useFormResetListener = (
libRef: React.MutableRefObject<HTMLTextAreaElement | null>,
listener: (event: Event) => any,
) => {
useListener(document.body, 'reset', (ev) => {
if (libRef.current!.form === ev.target) {
listener(ev);
}
});
};

export const useWindowResizeListener = (listener: (event: UIEvent) => any) => {
useListener(window, 'resize', listener);
};
Expand Down
12 changes: 12 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
useComposedRef,
useWindowResizeListener,
useFontsLoadedListener,
useFormResetListener,
} from './hooks';
import { noop } from './utils';

Expand Down Expand Up @@ -98,6 +99,17 @@ const TextareaAutosize: React.ForwardRefRenderFunction<

if (isBrowser) {
React.useLayoutEffect(resizeTextarea);
useFormResetListener(libRef, () => {
if (!isControlled) {
const node = libRef.current!;
const currentValue = node.value;
requestAnimationFrame(() => {
if (currentValue !== node.value) {
resizeTextarea();
}
});
}
});
useWindowResizeListener(resizeTextarea);
useFontsLoadedListener(resizeTextarea);
return <textarea {...props} onChange={handleChange} ref={ref} />;
Expand Down
Loading

0 comments on commit 8c47e31

Please sign in to comment.