skip to Main Content

I’m implementing a "characters left" feature for a textarea. When the user types it should countdown to zero and then stop the user entry. I’m using a useRef to bind to the textarea and output it’s length value in the paragraph but it’s not working although cntCharLeft.current.value.length is printing out correctly in the onChange method in textarea. Error message: Uncaught TypeError: Cannot read properties of undefined (reading 'length')

How do I print out the length of the ref in the paragraph to display the number of characters left and then stop the user input once the maximum (250) characters has been reached?

const cntCharLeft=useRef(0);

const submitHandler=(e)=>{
    ......
}

return(
    <Card className={styles.content} >
        <form onSubmit={submitHandler}>
            <textarea rows='6' ref={cntCharLeft} onChange={e=>{
                console.log(cntCharLeft.current.value.length)
            }} />
            <p className={styles.charsLeft} >{250-cntCharLeft.current.value.length} characters left</p>
            <Button type='submit'>Enter</Button>
        </form>
    </Card>
)

2

Answers


  1. While you’re using useRef, note that the change in the text area is not forcing a re-render. Consider making the text area a controlled input, placing the target value in state — either that, or on calls to onChange, place the length of the input in state. Both of these options remove the dependence on refs, and force component re-renders on text area value changes.

    Login or Signup to reply.
  2. You can use the maxlength attribute on the <textarea> HTML element to restrict the number of characters.

    Also you should consider to use useState() to store the value within the textarea. By doing so the component re-renders and the character count updates. Also by using onInput instead of onChange you ensure that the state is updated on every keystroke.

    function Textarea({ maxLength }){
    const [value, setValue] = React.useState("");
    
    function handleInput(e){
      const newValue = e.target.value;
      if(newValue.length <= maxLength){
        setValue(newValue);
      }
    }
    
    function submitHandler(){
      console.log("Submitted form");
    }
    
    return(
            <form onSubmit={submitHandler}>
                <textarea rows='6' onInput={handleInput} maxlength={maxLength} />
                <p>{maxLength - value.length} characters left</p>
                <button type='submit'>Enter</button>
            </form>
    );
    }
    
    ReactDOM.render(<Textarea maxLength={25} />, document.getElementById('root'));
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search