Как настроить фокус на пользовательский ввод в ReactJS с помощью useRef и react-хуков?

#javascript #reactjs #react-hooks

#javascript #reactjs #реагирующие хуки

Вопрос:

Я использую пользовательский элемент ввода и хочу настроить фокус на нем после первоначального рендеринга. Вот мой пользовательский элемент ввода: (хотя и простой)

 import React from 'react';
import './Input.scss';

const input = (props) => (
    <input 
        type={props.inputtype} 
        className="input" 
        placeholder={props.hint}
        style={{width: props.width}} {...props}/>
);

export default input;
  

И вот как я использую его в своем функциональном компоненте:

 const SignupPopup = (props) => {

const inputEmailRef = useRef(null);
//...
useEffect(() => {
    inputEmailRef.current.focus();
}, []);

return ( 
   <Input
      inputtype="email"
      hint="Email"
      width="100%"
      id="inputemail"
      ref={inputEmailRef}
      value={email}
      required
      onBlur={emailBlurHandler}
      onChange={inputChangeHandler}
      />);
}
  

Ошибка:

Ошибка типа: не удается прочитать свойство ‘focus’ null

введите описание изображения здесь

Все примеры и коды, которые я видел, работают только с собственным <input ref={myRef} /> элементом, но есть ли какой-либо способ сделать это в пользовательском элементе ввода или обернутом элементе ввода?

Ответ №1:

Вы должны использовать React.forwardRef для передачи ref в native input в своем пользовательском компоненте:

 import React from 'react';
import './Input.scss';

const input = React.forwardRef((props, ref) => (
    <input 
        type={props.inputtype} 
        className="input" 
        placeholder={props.hint}
        style={{width: props.width}}
        ref={ref}
        {...props}
    />
));

export default input;
  

Подробнее: — https://en.reactjs.org/docs/forwarding-refs.html

Комментарии:

1. Спасибо за ответ, он исправил ошибку, но, к сожалению focus , еще не установлен для элемента ввода! Есть идеи?

2. если вы хотите настроить фокус только на mount, вы можете просто попробовать установить prop autoFocus . См . codesandbox.io/s/suspicious-rain-ov0i6?file=/src/App.js:284-293

Ответ №2:

Вы должны передать с ref помощью React.forwardRef.

Таким образом, вы можете получить доступ к ссылке любого компонента React в родительском компоненте.

 const Input = React.forwardRef((props, ref) => (
     <input 
        ref={ref}
        type={props.inputtype} 
        className="input" 
        placeholder={props.hint}
        style={{width: props.width}} 
        {...props}
     />
));

  

Комментарии:

1. Спасибо за ответ, он исправил ошибку, но, к сожалению, фокус еще не установлен на элементе ввода! Есть идеи?

Ответ №3:

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

В React (протестирован на версии 17.0.2) вы можете использовать useRef hook для ссылки на определенный элемент. В этом случае вам нужно будет

  1. Импорт useRef . Это можно сделать так:
 import { useRef } from "react";
  
  1. Внутри вашего компонента (ранее return ) вы должны добавить a const , который будет вызывать useRef метод, который мы только что импортировали:
 const inputRef = useRef();
  
  1. Затем вам нужно сослаться inputRef на элемент:
 <input
    ref={inputRef}
    placeholder="Enter a value"
/>
  
  1. Наконец, вы можете делать с этим элементом все, что вам нужно, например, обращаться к нему следующим образом inputRef.current :
 inputRef.current.select(); // or inputRef.current.focus(); in your case
  

 'use strict';

const e = React.createElement;

const App = () => {


  const inputRef = React.useRef();
  
  const handleSubmit = (e) => {
    e.preventDefault();
    inputRef.current.select();
    // you could also use inputRef.current.focus() if you only want to focus the input
  };
  
  return(
    <form onSubmit={handleSubmit}>
      <h2> useRef select input example </h2>
      <input
        placeholder="Other input that I dont want to focus"
      />
      <input
        ref={inputRef}
        placeholder="Enter a value"
      />
      <button
        type="submit"
      > 
        Submit
      </button>
    </form>  
  );

}


const domContainer = document.querySelector('#root');ReactDOM.render(e(App), domContainer);  
 body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  padding: 10px 70px;
  text-align: center;
  color: #DDD;
  background-color: #222;
  }

form {
  padding: 0 20%;
  display: flex;
  flex-direction: column;
}

form * {
  margin-bottom: 0.5rem;

}  
 <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<!-- Don't use this in production: -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

<div id="root"></div>