#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 для ссылки на определенный элемент. В этом случае вам нужно будет
- Импорт
useRef
. Это можно сделать так:
import { useRef } from "react";
- Внутри вашего компонента (ранее
return
) вы должны добавить aconst
, который будет вызыватьuseRef
метод, который мы только что импортировали:
const inputRef = useRef();
- Затем вам нужно сослаться
inputRef
на элемент:
<input
ref={inputRef}
placeholder="Enter a value"
/>
- Наконец, вы можете делать с этим элементом все, что вам нужно, например, обращаться к нему следующим образом
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>