How to dynamically adjust textarea height with React?
Asked Answered
B

4

5

I want to adjust my textarea height dynamically with Refs and pass it to the state but it don't work correctly.

I created a codesandbox to help you to understand what exactly I want.

https://codesandbox.io/s/ol5277rr25

Buffybuford answered 28/2, 2019 at 1:42 Comment(2)
what exactly do you want? Could you edit your question to explain it better in plain english text?Negotiant
it's simple I want the height of my textarea to adapt according to the text.Buffybuford
P
14

You can solve this by using useRef and useLayoutEffect built-in hooks of react. This approach updates the height of the textarea before any rendering in the browser and therefor avoids any "visual update"/flickering/jumping of the textarea.

import React from "react";

const MIN_TEXTAREA_HEIGHT = 32;

export default function App() {
  const textareaRef = React.useRef(null);
  const [value, setValue] = React.useState("");
  const onChange = (event) => setValue(event.target.value);

  React.useLayoutEffect(() => {
    // Reset height - important to shrink on delete
    textareaRef.current.style.height = "inherit";
    // Set height
    textareaRef.current.style.height = `${Math.max(
      textareaRef.current.scrollHeight,
      MIN_TEXTAREA_HEIGHT
    )}px`;
  }, [value]);

  return (
    <textarea
      onChange={onChange}
      ref={textareaRef}
      style={{
        minHeight: MIN_TEXTAREA_HEIGHT,
        resize: "none"
      }}
      value={value}
    />
  );
}

https://codesandbox.io/s/react-textarea-auto-height-s96b2

Piggish answered 1/2, 2021 at 9:58 Comment(0)
T
6

Here's a simple solution that doesn't involve refs. The textarea is dynamically adusted using some CSS and the rows attribute. I used this myself, recently (example: https://codesandbox.io/embed/q8174ky809).

In your component, grab the textarea, calculate the current number of rows, and add 1:

const textArea = document.querySelector('textarea')
const textRowCount = textArea ? textArea.value.split("\n").length : 0
const rows = textRowCount + 1

return (
  <div>
    <textarea
      rows={rows}
      placeholder="Enter text here."
      onKeyPress={/* do something that results in rendering */}
      ... />
  </div>
)

And in your CSS:

textarea {
  min-height: 26vh; // adjust this as you see fit
  height: unset; // so the height of the textarea isn't overruled by something else
}
Trampoline answered 6/5, 2019 at 15:25 Comment(2)
Note that onKeyDown instead of onKeyPress will handle deletion as well.Trampoline
this only works properly without line wrapping. if a line is wrapped, that's 2 lines counting as 1... see RandomDude's answer for a more robust approach.Bobbybobbye
M
0

You can check the repo. Or you can add the package to your project.

https://github.com/andreypopp/react-textarea-autosize

Also if you really willing to learn how the logic working exactly;

https://github.com/andreypopp/react-textarea-autosize/blob/master/src/calculateNodeHeight.js

There is a source code with all calculations together.

Mymya answered 28/2, 2019 at 4:10 Comment(3)
Thank you I already used the react-textarea-autosize and react-autosize-textarea but in my case I really want to adjust the textarea height on my own, with refs & the stateBuffybuford
That's why i shared the source code. I can write your code but then you won't understand to read open source code. It could be come to you little bit confusing first. To encourage to you is my business with some help. To understand and write the code from the logic is also yours.Mymya
I tried but I wanted a simple solution.. not too much complex like that. I'm sure there is a solution much easier with Refs and the State for doing that. I made a codesandbox with the base logic, it work but not correctly, I think a little thing escapes me.. codesandbox.io/s/ol5277rr25Buffybuford
H
0

I was faced with inserting a texarea into the cell, and it increased as I entered text. I tried it in different ways. As a result, I made the cell itself . The React showed an error without the suppressContentEditableWarning={true} property. But it works in chrome and firefox as needed. Also, the onChange event does not work. Used the onInput={handleInputChange} event. And since there is no value in , I took event.target.textContent. I don't know how safe and correct this is. Therefore, you do all this under your own responsibility.

Huguenot answered 1/11 at 18:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.