I'm using this example to set the height of the textarea.
but the size of the textarea is not set automatically if the textarea has a value.
https://codesandbox.io/s/autosize-textarea-forked-wdowvr?file=/src/App.tsx
import { useRef, useState } from "react";
import "./styles.css";
export default function App() {
const [value, setValue] = useState("");
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const handleChange = (evt) => {
const val = evt.target?.value;
setValue(val);
};
return (
<div className="App">
<label htmlFor="review-text">Review:</label>
<textarea
id="review-text"
onChange={handleChange}
onInput={(e: React.FormEvent<HTMLTextAreaElement>) => {
e.currentTarget.style.height = e.currentTarget.scrollHeight "px";
}}
ref={textAreaRef}
rows={1}
value={value}
/>
</div>
);
}
how can i fix this issue?
CodePudding user response:
You can use the following snippets to adjust the height on loading the component.
Just for demo purposes:
const [value, setValue] = useState(
"already has a value with\nmore text\nand even more"
);
const textAreaRef = useRef<HTMLTextAreaElement>(null);
You can access the ref once it is set. useEffect
will do the trick here.
useEffect(() => {
if (textAreaRef && textAreaRef.current) {
textAreaRef.current.style.height = textAreaRef.current.scrollHeight 'px';
}
}, []);
https://codesandbox.io/s/autosize-textarea-forked-symr7p?file=/src/App.tsx
CodePudding user response:
You also need to set the height once the DOM
is mounted. This way it can respond to whatever value is in there before any user input.
I did this with the useEffect
hook. (Don't forget to import
it from react
).
I also tweaked the method of changing the height a bit, because it wasn't working properly.
import { useRef, useState, useEffect } from "react";
import "./styles.css";
export default function App() {
const [value, setValue] = useState("");
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const handleChange = (evt) => {
const val = evt.target?.value;
setValue(val);
};
const resizeTextarea = (t: HTMLTextAreaElement) => {
t.style.height = "auto";
const p = parseFloat(window.getComputedStyle(t, null).getPropertyValue("padding-top"))
parseFloat(window.getComputedStyle(t, null).getPropertyValue("padding-bottom"));
t.style.height = t.scrollHeight - p "px";
}
const handleInput = (e: React.FormEvent<HTMLTextAreaElement>) => {
resizeTextarea(e.currentTarget);
}
useEffect(() => {
const t = textAreaRef.current;
if (t != null) {
t.style.overflowY = 'hidden';
resizeTextarea(t);
}
},[]);
return (
<div className="App">
<label htmlFor="review-text">Review:</label>
<textarea
id="review-text"
onChange={handleChange}
onInput={handleInput}
ref={textAreaRef}
rows={1}
value={value}
/>
</div>
);
}
https://codesandbox.io/s/autosize-textarea-forked-s39ur2?file=/src/App.tsx:0-1172