在组件渲染后,react如何设置聚焦在特定文本字段上?
文档似乎建议使用参考,例如:
在渲染函数的输入字段上设置ref="nameInput",然后调用:
this.refs.nameInput.getInputDOMNode().focus();
但是我该把它叫什么呢?我在几个地方试过了,但都不行。
在组件渲染后,react如何设置聚焦在特定文本字段上?
文档似乎建议使用参考,例如:
在渲染函数的输入字段上设置ref="nameInput",然后调用:
this.refs.nameInput.getInputDOMNode().focus();
但是我该把它叫什么呢?我在几个地方试过了,但都不行。
当前回答
这一点对我很有用:
<input autoFocus={true} />
其他回答
重点关注功能组件使用createRef
给使用功能组件的开发人员。这似乎很合适。点击按钮后,焦点发生在inputfield上。我也附上了CodeSandbox链接。
import React from 'react';
export default function App() {
const inputRef = React.createRef();
return <>
<input ref={inputRef} type={'text'} />
<button onClick={() => {if (inputRef.current) { inputRef.current.focus() }}} >
Click Here
</button>
</>
}
https://codesandbox.io/s/blazing-http-hfwp9t
自动对焦对我来说效果最好。我需要将一些文本更改为双击文本的输入,所以这是我最终得到的:
<input autoFocus onFocus={this.setCaretToEnd} value={this.state.editTodo.value} onDoubleClick={this.updateTodoItem} />
注意:要修复React在文本开头放置插入符号的问题,请使用以下方法:
setCaretToEnd(event) {
var originalText = event.target.value;
event.target.value = '';
event.target.value = originalText;
}
在这里找到: https://coderwall.com/p/0iz_zq/how-to-put-focus-at-the-end-of-an-input-with-react-js
我刚刚遇到了这个问题,我正在使用react 15.0.1 15.0.2,我正在使用ES6语法,并没有完全得到我需要的其他答案,因为v.15下降了几周前和一些这。Refs属性被弃用并移除。
总的来说,我需要的是:
当组件挂载时,关注第一个输入(字段)元素 关注带有错误的第一个输入(字段)元素(提交后)
我用的是:
React容器/表示组件 回来的 React-Router
聚焦第一个输入元素
我在页面上的第一个<input />上使用autoFocus={true},这样当组件挂载时,它就会得到焦点。
关注带有错误的第一个输入元素
这需要更长的时间,也更复杂。为了简洁起见,我省略了与解决方案无关的代码。
Redux Store / State
我需要一个全局状态来知道我是否应该设置焦点,并在它被设置时禁用它,这样我就不会在组件重新呈现时重新设置焦点(我将使用componentDidUpdate()来检查设置焦点)。
这可以根据您的应用程序进行设计。
{
form: {
resetFocus: false,
}
}
容器组件
组件将需要设置resetfocus属性,如果它最终将焦点设置在自己身上,则需要使用callBack来清除该属性。
还要注意的是,我将我的Action creator组织到单独的文件中,主要是因为我的项目相当大,我想把它们分成更易于管理的块。
import { connect } from 'react-redux';
import MyField from '../presentation/MyField';
import ActionCreator from '../actions/action-creators';
function mapStateToProps(state) {
return {
resetFocus: state.form.resetFocus
}
}
function mapDispatchToProps(dispatch) {
return {
clearResetFocus() {
dispatch(ActionCreator.clearResetFocus());
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyField);
表示组件
import React, { PropTypes } form 'react';
export default class MyField extends React.Component {
// don't forget to .bind(this)
constructor(props) {
super(props);
this._handleRef = this._handleRef.bind(this);
}
// This is not called on the initial render so
// this._input will be set before this get called
componentDidUpdate() {
if(!this.props.resetFocus) {
return false;
}
if(this.shouldfocus()) {
this._input.focus();
this.props.clearResetFocus();
}
}
// When the component mounts, it will save a
// reference to itself as _input, which we'll
// be able to call in subsequent componentDidUpdate()
// calls if we need to set focus.
_handleRef(c) {
this._input = c;
}
// Whatever logic you need to determine if this
// component should get focus
shouldFocus() {
// ...
}
// pass the _handleRef callback so we can access
// a reference of this element in other component methods
render() {
return (
<input ref={this._handleRef} type="text" />
);
}
}
Myfield.propTypes = {
clearResetFocus: PropTypes.func,
resetFocus: PropTypes.bool
}
概述
一般的想法是,每个表单字段,可能有一个错误,并被集中需要检查自己,如果它需要设置自己的焦点。
需要执行业务逻辑来确定给定的字段是否是要设置焦点的正确字段。这里没有显示这一点,因为它取决于各个应用程序。
当提交表单时,该事件需要将全局焦点标志resetFocus设置为true。然后,当每个组件更新自己时,它会看到它应该检查它是否得到焦点,如果它得到了,分派事件重置焦点,这样其他元素就不必继续检查了。
编辑 作为旁注,我在一个“utilities”文件中有我的业务逻辑,我只是导出了这个方法,并在每个shouldfocus()方法中调用它。
干杯!
要将焦点移动到新创建的元素上,您可以将元素的ID存储在状态中,并使用它来设置自动聚焦。如。
export default class DefaultRolesPage extends React.Component {
addRole = ev => {
ev.preventDefault();
const roleKey = this.roleKey++;
this::updateState({
focus: {$set: roleKey},
formData: {
roles: {
$push: [{
id: null,
name: '',
permissions: new Set(),
key: roleKey,
}]
}
}
})
}
render() {
const {formData} = this.state;
return (
<GridForm onSubmit={this.submit}>
{formData.roles.map((role, idx) => (
<GridSection key={role.key}>
<GridRow>
<GridCol>
<label>Role</label>
<TextBox value={role.name} onChange={this.roleName(idx)} autoFocus={role.key === this.state.focus}/>
</GridCol>
</GridRow>
</GridSection>
))}
</GridForm>
)
}
}
通过这种方式,没有任何文本框获得页面加载的焦点(就像我想要的那样),但是当你按下“添加”按钮来创建一个新记录时,那么这个新记录就会获得焦点。
由于autoFocus不会再次“运行”,除非组件重新挂载,所以我不必费心取消this.state.focus(即当我更新其他状态时,它不会一直窃取焦点)。
关注坐骑
如果你只是想在一个元素挂载(初始渲染)时聚焦它,简单使用autoFocus属性就可以了。
<input type="text" autoFocus />
动态焦点
要动态控制焦点,请使用通用函数对组件隐藏实现细节。
React 16.8 +功能组件- useFocus钩子
const FocusDemo = () => {
const [inputRef, setInputFocus] = useFocus()
return (
<>
<button onClick={setInputFocus} >
Focus
</button>
<input ref={inputRef} />
</>
)
}
const useFocus = () => {
const htmlElRef = useRef(null)
const setFocus = () => {htmlElRef.current && htmlElRef.current.focus()}
return [ htmlElRef, setFocus ]
}
完整的演示
React 16.3 +类组件-使用
class App extends Component {
constructor(props){
super(props)
this.inputFocus = utilizeFocus()
}
render(){
return (
<>
<button onClick={this.inputFocus.setFocus}>
Focus
</button>
<input ref={this.inputFocus.ref}/>
</>
)
}
}
const utilizeFocus = () => {
const ref = React.createRef()
const setFocus = () => {ref.current && ref.current.focus()}
return {setFocus, ref}
}
完整的演示