skip to Main Content

I have a useEffect

useEffect(() => {
  const dateOfBirthInput = document.getElementById("date-of-birth-input") as HTMLInputElement
  const dataLength = dateOfBirth.length
  dateOfBirthInput.selectionStart = dataLength
  dateOfBirthInput.selectionEnd = dataLength
}, [dateOfBirth])

Here I’m getting the input with getElementById, then I can’t set selectionStart on the input.

While this code sets selectionStart and selectionEnd

const dateOfBirthOnClick = (e: React.MouseEvent<HTMLInputElement>) => {
  const dataLength = dateOfBirth.length;
  (e.target as HTMLInputElement).selectionStart = dataLength;
  (e.target as HTMLInputElement).selectionEnd = dataLength
}

This code works, the previous doesn’t, is this some kind of "When working with React you should not use Vanilla JS" bug.

Edit:

I’m sorry I added the id to the wrong element. It had to be the input.

<div id="date-of-birth-input">
  <input type="text" />
</div>

2

Answers


  1. I can’t find any documentation or reference to either selectionStart or selectionEnd.

    However, there’s a setSelectionRange method:

    input.setSelectionRange(data.length, data.length)
    

    When using react, there are not many cases that require you to directly query the dom. Maybe you wanted to use a ref to your input instead?

    EDIT:

    The docs for setSelectionRange also state this:

    Note that according to the WHATWG forms spec selectionStart, selectionEnd properties and setSelectionRange method apply only to inputs of types text, search, URL, tel and password.

    Ergo, the Selection API is unavailable on date inputs for instance.

    Login or Signup to reply.
  2. In your useEffect, you’re trying to set the selection on the dateOfBirthInput based on the dateOfBirth value. If the dateOfBirth value is not updated by the time your useEffect runs, it might lead to unexpected behavior.

    In other code, in your dateOfBirthOnClick function, you’re setting the selection directly based on the e.target (the input element) without relying on an external value like dateOfBirth. This approach is more reliable because it doesn’t depend on the timing of state updates.

    Consider using useRef too.

    I believe the following code is a more valid and solid approach to the problem using React :

    import { useEffect, useRef } from 'react';
    
    function YourComponent({ dateOfBirth }) {
      const dateOfBirthInputRef = useRef<HTMLInputElement>(null);
    
      useEffect(() => {
        const dateOfBirthInput = dateOfBirthInputRef.current;
        if (dateOfBirthInput) {
          const dataLength = dateOfBirth.length;
          dateOfBirthInput.selectionStart = dataLength;
          dateOfBirthInput.selectionEnd = dataLength;
        }
      }, [dateOfBirth]);
    
      return (
        <input
          id="date-of-birth-input"
          ref={dateOfBirthInputRef}
          type="text"
          value={dateOfBirth}
          onChange={(e) => {
            // Update the dateOfBirth value in your component's state here
          }}
        />
      );
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search