React useRef / forwardRef не работает должным образом при фокусировке переключателя - PullRequest
1 голос
/ 10 июля 2020

Я собрал здесь небольшую демонстрацию: https://codesandbox.io/s/bold-meitner-r3wzq?file= / src / App. js

Когда я нажимаю кнопку, чтобы отобразить и сфокусироваться на моем первом переключателе - Мой стиль радио не применяется. Хотя, если вы нажмете пробел сразу после этого, он сфокусируется на правильном элементе.

Странно, если я сфокусируюсь после тайм-аута 1 мс, он будет работать, как ожидалось. Очевидно, это скорее взлом, чем решение ...

Я чувствую, что мне здесь не хватает чего-то очень простого, любая помощь будет отличной!

Спасибо !!

Альтернативно - это весь код, необходимый для репликации:

import React from "react";
import styled from "styled-components";
import "./styles.css";

const { useRef, forwardRef, useState } = React;

const Button = ({ onClick }) => (
  <button onClick={onClick}>Click me to show and focus radio buttons</button>
);

const Fieldset = styled.fieldset`
  display: ${props => (props.isVisible ? "block" : "none")};

  input {
    :focus {
      outline: 5px solid red;
    }
  }
`;

const RadioButtons = forwardRef(({ isVisible, legend }, ref) => (
  <Fieldset isVisible={isVisible}>
    <legend>{legend}</legend>
    <label for="one">One</label>
    <input ref={ref} type="radio" id="one" name="radios" />
    <label for="two">Two</label>
    <input type="radio" id="two" name="radios" />
  </Fieldset>
));

export default function App() {
  const [isVisible, setIsVisible] = useState(false);
  const inputRef = useRef();

  const focusInput = () => {
    setIsVisible(true);

    // This doesn't work as expected
    inputRef.current.focus();

    // This does - But it definitely doesn't feel like a "solution"
    // setTimeout(() => {
    //   inputRef.current.focus();
    // }, 1);
  };

  return (
    <>
      <Button onClick={focusInput} />
      <RadioButtons
        isVisible={isVisible}
        ref={inputRef}
        legend="Radio Legend"
      />
    </>
  );
}


Ответы [ 2 ]

1 голос
/ 10 июля 2020

Вы должны поместить логин фокусировки внутри хука useEffect, как это

export default function App() {
  const [isVisible, setIsVisible] = useState(false);
  const inputRef = useRef();

  const focusInput = () => {
    setIsVisible(true);
  };

  React.useEffect(() => {
    if (isVisible) {
      inputRef.current.focus();
    }
  }, [isVisible]);

  return (
    <>
      <Button onClick={focusInput} />
      <RadioButtons
        isVisible={isVisible}
        ref={inputRef}
        legend="Radio Legend"
      />
    </>
  );
}

Вот ссылка

1 голос
/ 10 июля 2020

Как всегда кажется go ... Вы чувствуете, что исчерпали все варианты - Затем вы пишете вопрос, и тогда вы сразу же находите ответ!

В этом случае - Перемещение фокуса refs в useEffect, который наблюдает за isVisible, добился цели

useEffect(() => {
    // I check here because my actual code toggles isVisible 
    if (isVisible) inputRef.current.focus();
}, [isVisible]);

Тем не менее интересно посмотреть, можно ли это сделать лучше, хотя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...