skip to Main Content

I am working on a project in Next.js13 and I am trying to create a custom textarea component. I would like this component to add an event listener to itself (allowing to auto-adjust its height as the user types). This is the part of the code relating to this issue:

const textarea = (
    <textarea 
        id={id}
        className={styles.input} 
        {...fieldProps} /> 
);

textarea.addEventListener("input", function(e){
    this.style.height = "auto";
    this.style.height = this.scrollHeight + "px";
})

return (
    {textarea}
)

This code generates the errors "TypeError: textarea.addEventListener is not a function" and "Property ‘addEventListener’ does not exist on type ‘Element’."

How can I add this event listener just to the text area created by this component?

Constraints and Previously Attempted Solutions

  1. I want the user to be able to specify the id (but not to require this), so I cannot use document.getElementById().

  2. Rewriting the addEventListener line as the following eliminates "Property ‘addEventListener’ does not exist on type ‘Element’" but "TypeError: textarea.addEventListener is not a function" remains:

    (textarea as unknown as HTMLTextAreaElement).addEventListener("input", function(e){
        this.style.height = "auto";
        this.style.height = this.scrollHeight + "px";
    })
    
  3. Using document.getElementsByTag('textarea') and then looping through all of the returned textareas and adding the event listener does work. However, if I have multiple textareas on one page, this seems to be adding the event listener twice. And I could hypothetically have a textarea on the page that is part of a different component, which I don’t want this event listener to be added to.

2

Answers


  1. If you are open to using a library instead of implementing this functionality yourself, there is a great library for it called
    react-textarea-autosize.

    If you want to implement it yourself, you can still use this repo as a guide.

    Login or Signup to reply.
  2. In React, you cannot directly add event listeners to elements created in JSX like you would with vanilla JavaScript. Instead, you should use the React way of handling events by using the onChange prop on the textarea element.

    TEXTAREA_COMPONENT.js

    import React, { useState } from 'react';
    
    const CustomTextarea = ({ id, ...fieldProps }) => {
      const [value, setValue] = useState('');
      const [height, setHeight] = useState('auto');
    
      const handleChange = (e) => {
        setValue(e.target.value);
        setHeight('auto');
        setHeight(e.target.scrollHeight + 'px');
      };
    
      return (
        <textarea
          id={id}
          className={styles.input}
          value={value}
          onChange={handleChange}
          style={{ height }}
          {...fieldProps}
        />
      );
    };
    
    export default CustomTextarea;
    

    APP.js

    import React from 'react';
    import CustomTextarea from './path/to/CustomTextarea';
    
    const App = () => {
      return (
        <div>
          <CustomTextarea id="your-textarea" />
          {/* other content */}
        </div>
      );
    };
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search