как реагировать на программный фокус
Я пытаюсь реализовать очень простой вариант использования, функцию пользовательского интерфейса, где:
- В нем есть ярлык с некоторым контентом
- Если щелкнуть, текстовый ввод заменяет его содержимым метки
- Пользователь может редактировать содержимое
- При нажатии кнопки ввод скрывается и метка возвращается с обновленным контентом
Я мог бы, наконец, все правильно (на самом деле с бэкэндом MongoBD, редуксом и т.д.), И единственное, что я никогда не мог сделать (полный день в поиске по Google и чтение подобных сообщений) был следующим:
Когда появится мой ввод текста, я не могу перенести на него фокус! Сначала я устал так:
<div className={((this.state.toggleWordEdit) ? '' : 'hidden')}>
<input id={this.props.word._id} className="form-control"
ref="updateTheWord"
defaultValue={this.state.word}
onChange={this.handleChange}
onKeyPress={this.handleSubmit}
autoFocus={this.state.toggleWordEdit}/></div>
<div className={((this.state.toggleWordEdit) ? 'hidden' : '')}>
<h3 onClick={this.updateWord}>
{this.state.word}</h3>
</div>
но autoFocus уверен, что не работал (я "догадываюсь", потому что форма визуализируется, но в скрытом состоянии, делая autoFocus бесполезным).
Затем я попытался в моем this.updateWor, много предложений, которые я нашел в google и SOF:
this.refs.updateTheWord.focus();
которые вместе с подобными предложениями все не сработали. Также я попытался обмануть Реакт, чтобы убедиться, что я могу что-то сделать! Я использовал реальный DOM:
const x = document.getElementById(this.props.word._id);
x.focus();
и это тоже не сработало. Одна вещь, которую я даже не мог понять, чтобы выразить это, - это предложение вроде этого: имея ref как метод (я "догадываюсь"), я даже не пробовал его, потому что у меня есть кратность этих компонентов, и мне нужно ref для дальнейшего получения значения из, за компонент, и я не мог себе представить, если мой ref не назван, как я мог бы получить значение!
Так что, пожалуйста, дайте мне понять, помогая понять, что если я не использую форму (потому что мне нужен один блок ввода, заменяющий метку), как бы я мог сосредоточиться, когда класс CSS (Bootstrap) скрытый "пожалуйста?
Ответы
Ответ 1
То, как вы использовали рефери, - не самый предпочтительный способ, иначе это не лучшая практика. попробуйте что-нибудь подобное
class MyClass extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
this.textInput.current.focus();
}
render() {
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Set Focus"
onClick={this.focus}
/>
</div>
);
}
}
Обновление
Начиная с Реакции 16.3 и выше, вы можете использовать React.createRef()
API
class MyClass extends React.Component {
constructor(props) {
super(props);
// create a ref to store the textInput DOM element
this.textInput = React.createRef();
this.focus = this.focus.bind(this);
}
focus() {
// Explicitly focus the text input using the raw DOM API
// Note: we're accessing "current" to get the DOM node
this.textInput.current.focus();
}
render() {
// tell React that we want to associate the <input> ref
// with the 'textInput' that we created in the constructor
return (
<div>
<input
type="text"
ref={this.textInput} />
<input
type="button"
value="Set Focus"
onClick={this.focus}
/>
</div>
);
}
}
Ответ 2
Просто добавьте атрибут автофокуса на input
. (конечно в JSX
это autoFocus
)
<input autoFocus ...
Ответ 3
Используйте метод componentDidUpdate
чтобы каждый раз обновлять компонент
componentDidUpdate(prevProps, prevState) {
this.input.focus();
}
Ответ 4
крючок useFocus
// General Focus Hook
const useFocus = (initialFocus = false, id = "") => {
const [focus, setFocus] = useState(initialFocus)
const setFocusWithTrueDefault = (param) => setFocus(isBoolean(param)? param : true)
return ([
setFocusWithTrueDefault, {
autoFocus: focus,
key: '${id}${focus}',
onFocus: () => setFocus(true),
onBlur: () => setFocus(false),
},
])
}
const FocusDemo = () => {
const [labelStr, setLabelStr] = useState("Your initial Value")
const [setFocus, focusProps] = useFocus(true)
return (
<> {/* React.Fragment */}
<input
onChange={(e)=> setLabelStr(e.target.value)}
value={labelStr}
{...focusProps}
/>
<h3 onClick={setFocus}>{labelStr}</h3>
</>
)
}
Для более полной демонстрации [нажмите здесь] [1].
Ответ 5
Найдите пример здесь с помощью React Hooks: https://codepen.io/googol7/pen/MdrGaR
const { useEffect } = React
const setFocus = () => {
this.textInput.focus()
}
function App() {
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
setFocus()
})
return <div>
<button onClick={setFocus} className="btn btn-primary">
Set focus
</button>
<input ref={elem => (this.textInput = elem)} placeholder="Focus on me" />
</div>
}
Ответ 6
В дополнение к предыдущим ответам я добавил setTimeout
чтобы он работал
handleClick() {
if (this.searchInput) {
setTimeout(() => {
this.searchInput.focus();
}, 100);
}
}
где searchInput
- это jsx-ссылка ввода
<input
type="text"
name="searchText"
ref={(input) => { this.searchInput = input; }}
placeholder="Search" />
и handleClick()
представляет собой onClick
обработчик к любому элементу