Почему select () не работает в Safari с ReactJS? - PullRequest
0 голосов
/ 17 января 2019

Я бы хотел, чтобы TextField выделял весь текст, находящийся в данный момент в поле, всякий раз, когда я щелкаю / нажимаю / фокусируюсь на поле. Следующий код работает в Chrome (71.0.3578.98), но не в Safari (12.0.2). Есть идеи почему?

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

И все же этот статический HTML-файл без каких-либо React прекрасно работает в 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

Может кто-нибудь помочь мне понять, как заставить выделение работать в Safari с React?

Ответы [ 3 ]

0 голосов
/ 17 января 2019

Это хорошо известная проблема, вы можете обойти эту проблему, используя set timeout

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

Здесь работает пример . Я тестировал на сафари, работал без каких-либо проблем.

0 голосов
/ 17 января 2019

Когда такие вещи, как взаимодействие с DOM, терпят неудачу, это обычно связано с тем, как события запускаются синхронно / асинхронно в разных контекстах (реагируют на onclick) и даже в браузерах (иногда Safari имеет странные оптимизации).

Я предполагаю, что это будет работать, сделав его асинхронным, как:

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

0 голосов
/ 17 января 2019

Я думаю, что вы хотите использовать React ref для хранения ссылки на фактический элемент input DOM, чтобы вы могли вызывать select для него из метода onClick.

Посмотрите документы, у них есть хороший пример, который вы можете немного изменить в соответствии со своими потребностями: https://reactjs.org/docs/refs-and-the-dom.html

Это должно сработать, я думаю:

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

import "./styles.css";

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = React.createRef();
    this.selectTextInput = this.selectTextInput.bind(this);
  }

  selectTextInput() {
    this.textInput.current.select();
  }

  render() {
    return (
      <div>
        <input 
          type="text" 
          defaultValue="pizza" 
          ref={this.textInput} 
          onClick={this.selectTextInput}
        />
      </div>
    );
  }
}

function App() {
  return (
    <CustomTextInput />
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...