2

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>
  );
}

for example

how can i fix this issue?

DreamBold
  • 2,727
  • 1
  • 9
  • 24
xojorib957
  • 31
  • 4

2 Answers2

1

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

DreamBold
  • 2,727
  • 1
  • 9
  • 24
F. Müller
  • 3,969
  • 8
  • 38
  • 49
0

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

DreamBold
  • 2,727
  • 1
  • 9
  • 24
timlg07
  • 547
  • 6
  • 20