Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does select() not work on Safari with ReactJS?

Tags:

I'd like to get a TextField to select the whole text currently in the field whenever I click/tap/focus on the field. The following code works in Chrome (71.0.3578.98), but not in Safari (12.0.2). Any ideas why?

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  return (
    <>
      <h1>Test Focus React</h1>
      <input
        type="text"
        defaultValue="test"
        onFocus={event => {
          event.target.select();
        }}
      />
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit pkqzz7nxz0

And yet this static HTML file without any React works fine on Safari.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Test Focus JS</title>
  </head>
  <body>
    <h1>Test Focus JS</h1>
    <input type="text" value="test" onClick="this.select();" />
  </body>
</html>

Edit 6l20oq76jn

Can anyone help me see how to get the selection to work on Safari with React?

like image 516
EFC Avatar asked Jan 17 '19 05:01

EFC


2 Answers

When things like interacting with the DOM fail, it usually is related to how events fire synchronously / asynchronously in different contexts (react vs onclick), and browsers even (with Safari having weird optimisations sometimes).

I'm guessing it'll just work by making it async, like:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  return (
    <>
      <h1>Test Focus React</h1>
      <input
        type="text"
        defaultValue="test"
        onFocus={event => {
              // event properties must be copied to use async
              const target = event.target;
              setTimeout(() => target.select(), 0);
        }}
      />
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit test-focus-react

like image 119
Meligy Avatar answered Oct 22 '22 11:10

Meligy


This is well known issue, you can work around this basically using set timeout

onFocus={event => {
  setTimeout(event.target.select.bind(event.target), 20);
}}

Here is working example. I tested on safari worked without any issue.

like image 31
Whatatimetobealive Avatar answered Oct 22 '22 11:10

Whatatimetobealive