简体   繁体   中英

Can't clear text selection from textarea

Problem:

I have multiple textarea s that can be navigated using arrow keys. The textarea s are focused using ref.focus() .

When the textarea s are focused this way, the text selection is not cleared?

Screenshot

在此处输入图片说明

Expect

The text selection in the second textarea should be cleared when the first is clicked, or when the second textarea is focused again.

Code

import React, { useEffect, useRef, useState } from "react";

export const Test = () => {
  const [editingBlock, setEditingBlock] = useState<Number | null>(null);
  const textArea1Ref = useRef<HTMLTextAreaElement | null>(null);
  const textArea2Ref = useRef<HTMLTextAreaElement | null>(null);

  useEffect(() => {
    // set 1 focus
    if (editingBlock === 1 && textArea1Ref.current) {
      textArea1Ref.current.focus();

      // blur 2
      if (textArea2Ref.current) {
        textArea2Ref.current.blur();
      }

      // set 2 focus
    } else if (editingBlock === 2 && textArea2Ref.current) {
      textArea2Ref.current.focus();

      // blur 1
      if (textArea1Ref.current) {
        textArea1Ref.current.blur();
      }
    }
  }, [editingBlock]);

  return (
    <>
      <div>
        <textarea
          ref={textArea1Ref}
          value={"a really long string"}
          onBlur={(e) => setEditingBlock(null)}
          onKeyDown={(e) => {
            if (e.key === "ArrowDown") setEditingBlock(2);
          }}
          onClick={(e) => setEditingBlock(1)}
        />
      </div>
      <div>
        <textarea
          ref={textArea2Ref}
          value={"a really long string"}
          onBlur={(e) => {
            if (window.getSelection()) {
              window.getSelection()!.removeAllRanges(); // doesn't work
            }
            setEditingBlock(null);
          }}
          onClick={(e) => setEditingBlock(2)}
        />
      </div>
    </>
  );
};

The value will always be the same

You have set the value with a string, this will never change since it's a static value in the field.

If you would like to make the field changeable use some state, reducer or library to handle fields.

Here's an example

const [textArea1, setTextArea1] = useState<string>('');
...
return (
  ...
  <textarea
     ref={textArea1Ref}
     value={textArea1}
     onChange={(event) => setTextArea1(event.target.value)}
  />
  ...
)

To clear the field on blur you just need fire setTextArea1('') .

Hacky solution

I still don't fully understand why this is happening, but found a workaround solution for now:

In the textarea 's onBlur callback, simply use the following code:

if (textArea2Ref.current) {
    // if there's a range selection
    if (textArea2Ref.current.selectionStart !== textArea2Ref.current.selectionEnd) {
        // reset the range
        textArea2Ref.current.selectionStart = textArea2Ref.current.selectionEnd;

        // blur the textarea again, because setting the selection focuses it?
        textArea2Ref.current.blur();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM