React JS - как мне потерять фокус на элементе, на который только что нажали? - PullRequest
0 голосов
/ 27 октября 2019

У меня есть небольшое приложение реакции, в котором есть некоторые компоненты, которые называются InfoBox. каждый InfoBox создается с key (для React), id (для меня), name, top_pos', left_pos , a rings_visible boolean, and a focusOnRing callback sent from the parent (the object that instantiates the InfoBox es) as props to the InfoBox`

он создан в некотором родительском коде, подобном этому

 <InfoBox
              key={ele.key}
              id={ele.key}
              name={ele.name}
              top_pos={ele.top_pos}
              left_pos={ele.left_pos}
              focusOnRing={this._focusOnRing}
              rings_visible={(focused_ring === ele.key)}
            />

Вот полный src/info_box.js, с которым я работаю ...

import React from 'react'
import styled from 'styled-components'
import Rings from './rings'

const StyledBlurbBox = styled.div`
  border: solid 1px red;
  width: 10px;
  height: 10px;
  position: absolute;
  margin-left: 45px;
  margin-top: 50px;
  display: hidden;
`

const StyledInfoBox = styled.div`
  text-align: center;
  position: absolute;
  width: 100px;
  height: 100px;
  cursor: pointer;
`

const StyledH1 = styled.h1 `
  font-size: 1.2em;
  width: 100%;
`

export default class InfoBox extends React.Component {
  constructor({blurb}) {
    super()

    this.state = {
      name: (blurb ?  blurb.name : ""),
    }
  }


  render() {
    const top_pos = this.props.top_pos || 100
    const left_pos = this.props.left_pos || 400
    const {name, id, rings_visible, blurb} = this.props


    return (
      <div>
        <StyledInfoBox onClick={() => {this.props.focusOnRing(this.props.id) }}
         style={{top: top_pos + "%", left: left_pos + "%"}}>

          <Rings visible={rings_visible}
                 animation_sequence={['spinning', '']}/>

          <div className="vertical-center-container">
            <StyledH1>
              <button href="#" value={name}>{name}</button>
            </StyledH1>
          </div>
        </StyledInfoBox>


      </div>
    )
  }
}

МойПроблема лучше всего объясняется визуально, поэтому я объясню это на скриншотах.

Мой ожидаемый результат заключается в том, что когда я нажимаю на InfoBox (который оказывается StyledInfoBox ниже), вокруг него появляются некоторые кольца (это еще один компонент, называемый Rings)

Однако, когда я делаю щелчок, браузер (Chrome) помещает раздражающую синюю строку вокруг текста того, что я только что нажал (может быть, кнопка?), Чтобы это выглядело так:

enter image description here

Ожидаемый результат: синяя линия отсутствует, видны только кольца:

enter image description here

I Подумайте , что мне нужно сделать, это перехватить событие (это возможно / рекомендуется в React?) и размыть (или де-фокусировать) эту кнопку. но я не уверен, как это сделать.

один интересный эффект, который я узнаю о React, заключается в том, что когда виртуальный DOM повторно отображает (или мутирует) реальный DOM, элементы сохраняют свою фокусировку, в том числе если вы сфокусированы или размыты на элементе вDOM, как можно увидеть здесь.

Использование React 16.9.0

UPDATE # 1

моя реализация решения, предложенного @Nick с использованием React refs. обратите внимание на то, что здесь я добавил размытие к методу onClick. в ответе @ Ника ниже, он прикреплен к setTimeout.

import React from 'react'
import styled from 'styled-components'
import Rings from './rings'

const StyledBlurbBox = styled.div`
  border: solid 1px red;
  width: 10px;
  height: 10px;
  position: absolute;
  margin-left: 45px;
  margin-top: 50px;
  display: hidden;
`

const StyledInfoBox = styled.div`
  text-align: center;
  position: absolute;
  width: 100px;
  height: 100px;
  cursor: pointer;
`

const StyledH1 = styled.h1 `
  font-size: 1.2em;
  width: 100%;
`

export default class InfoBox extends React.Component {
  constructor({blurb}) {
    super()

    this.state = {
      name: (blurb ?  blurb.name : ""),
    }
    this.buttonRef = React.createRef();
  }


  render() {
    const top_pos = this.props.top_pos || 100
    const left_pos = this.props.left_pos || 400
    const {name, id, rings_visible, blurb} = this.props


    return (
      <div >
        <StyledInfoBox onClick={() => { this.buttonRef.current.blur(); this.props.focusOnRing(this.props.id) }}
         style={{top: top_pos + "%", left: left_pos + "%"}}>

          <Rings visible={rings_visible}
                 animation_sequence={['spinning', '']}/>

          <div className="vertical-center-container">
            <StyledH1>
              <button ref={this.buttonRef} href="#" value={name}>{name}</button>
            </StyledH1>
          </div>
        </StyledInfoBox>


      </div>
    )
  }
}

Ответы [ 2 ]

1 голос
/ 27 октября 2019

Вы можете получить доступ к элементам DOM в React, используя ref s. В следующем коде показан простой пример, который фокусируется на кнопке при начальной загрузке, а затем через три секунды не фокусируется на этом элементе.

Я бы настоятельно рекомендовал против решения CSS удалить контуры из элементов вводаи кнопки. Контуры - это специальные возможности, которые не должны быть изменены, если вы не замените их подходящей альтернативой.

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

import "./styles.css";

class App extends React.Component {
  constructor() {
    super();
    this.myRef = React.createRef();
  }

  componentDidMount() {
    this.myRef.current.focus();
    setTimeout(() => {
      this.myRef.current.blur();
    }, 3000);
  }

  render() {
    return (
      <div className="App">
        <button ref={this.myRef}>Thing</button>
      </div>
    );
  }

}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
0 голосов
/ 27 октября 2019

Если вам не нужен контур фокуса, вы можете просто использовать:

const StyledH1 = styled.h1 `
  font-size: 1.2em;
  width: 100%;
  button:focus{
        outline: none;
  }
`

Как упоминалось в комментариях, это вызовет проблемы с доступностью, поскольку для тех, кто перемещается по вашей странице с помощью клавиатуры, не будет видимых указаний

Вы можете добавить другую тему / стиль фокуса кнопки, чтобы вновь предоставить доступность:

  button:focus{
        outline: thin dotted #E1CA80;
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...