渲染后将焦点设置在输入上

时间:2015-03-05 23:28:23

标签: javascript reactjs

在渲染组件后,将焦点设置在特定文本字段上的反应方式是什么?

文档似乎建议使用refs,例如:

在渲染功能的输入字段上设置ref="nameInput",然后调用:

this.refs.nameInput.getInputDOMNode().focus(); 

但我应该在哪里打电话呢?我尝试了几个地方,但我无法让它发挥作用。

28 个答案:

答案 0 :(得分:682)

@ Dhiraj的回答是正确的,为方便起见,您可以使用autoFocus道具在安装时自动对焦输入:

<input autoFocus name=...

请注意,在jsx中它是autoFocus(大写字母F),而不像普通的旧HTML那样不区分大小写。

答案 1 :(得分:539)

您应该在componentDidMountrefs callback中执行此操作。像这样的东西

componentDidMount(){
   this.nameInput.focus(); 
}

&#13;
&#13;
class App extends React.Component{
  componentDidMount(){
    this.nameInput.focus();
  }
  render() {
    return(
      <div>
        <input 
          defaultValue="Won't focus" 
        />
        <input 
          ref={(input) => { this.nameInput = input; }} 
          defaultValue="will focus"
        />
      </div>
    );
  }
}
    
ReactDOM.render(<App />, document.getElementById('app'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.js"></script>
<div id="app"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:143)

从React 0.15 开始,最简洁的方法是:

<input ref={input => input && input.focus()}/>

答案 3 :(得分:51)

如果您只想在React中进行自动对焦,那很简单。

<input autoFocus type="text" />

如果您只是想知道放置该代码的位置,那么答案就在componentDidMount()中。

v014.3

componentDidMount() {
    this.refs.linkInput.focus()
}
  

在大多数情况下,您可以将引用附加到DOM节点,并完全避免使用findDOMNode。

在此处阅读API文档:https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode

答案 4 :(得分:25)

我刚刚遇到这个问题而且我使用的是反应 15.0.1 15.0.2并且我使用的是ES6语法并且没有得到我需要的东西从第15周以来的其他答案中删除了一些this.refs properties were deprecatedremoved

一般来说,我需要的是:

  1. 在组件安装
  2. 时聚焦第一个输入(字段)元素
  3. 使用错误(提交后)
  4. 聚焦第一个输入(字段)元素

    我正在使用:

    • React Container / Presentation Component
    • 终极版
    • 阵营-路由器

    聚焦第一个输入元素

    我在页面的第一个autoFocus={true}上使用了<input />,这样当组件安装时,它就会得到焦点。

    使用错误

    聚焦第一个输入元素

    这花费的时间更长,更复杂。为了简洁起见,我要保留与解决方案无关的代码。

    Redux商店/州

    我需要一个全局状态来知道我是否应该设置焦点并在设置时禁用它,所以当组件重新渲染时我不会重新设置焦点(我将会是使用componentDidUpdate()检查设置焦点。)

    这可以按照您认为适合您的应用程序进行设计。

    {
        form: {
            resetFocus: false,
        }
    }
    

    容器组件

    组件需要设置resetfocus属性,并且如果最终将焦点设置在自身上,则需要使用callBack清除属性。

    另请注意,我将Action Creators组织成单独的文件,主要是因为我的项目相当大,我想将它们分解为更易于管理的块。

    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。然后,当每个组件更新自己时,它会看到它应该检查它是否得到焦点,如果是,则调度事件以重置焦点,以便其他元素不必继续检查。

    修改的 作为旁注,我将我的业务逻辑放在&#34;实用程序&#34;文件,我刚刚导出了方法,并在每个shouldfocus()方法中调用它。

    干杯!

答案 5 :(得分:25)

您不需要使用参考

React作为框架提供的主要优点是代码可以描述性地编写,而不必强制性地编写。这很重要-它使代码更易于理解。使用Ref时,您的代码将变得更重要。

安装时关注一个元素

在大多数情况下,只需使用autoFocus属性即可。

<input type="text" autoFocus />

有条件地管理和转移焦点

根据某种逻辑,您可能希望将焦点从一个元素移到另一个元素(例如,在键入预期字符数时移至下一个字段)。 autoFocus属性的问题在于,它只能在组件首次渲染(安装)时设置焦点。因此,仅将属性的值从true更改为false不会有任何效果。

解决方案是每次焦点更改时都使用key属性重新安装元素。如果这样做,我们可以将对焦质量视为受控。

class InputW extends Component {
    state = {
        value: ""
        isFocused: false
    }

    handleChange = e => {
        this.setState({ value: e.target.value, isFocused: true })
    }

    deFocus = () => this.setState({isFocused: false})

    render(){
        return (
            <input
                onChange={this.handleChange}
                value={this.state.value}
                autoFocus={this.state.isFocused}
                key={this.state.isFocused}
                onBlur={this.deFocus}
            />
        )
    }
}

Example 1-单击按钮可使输入焦点,并输入3个字符,导致其散焦。 example 2-输入将焦点移到下一个字段元素。

答案 6 :(得分:23)

React文档现在有一个部分。 https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute

function onEdit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var cell = sheet.getActiveCell();
  var origValue = e.oldValue
 sheet.getRange('A1').setValue(origValue);
}

答案 7 :(得分:11)

参考。 @Dave对@ Dhiraj的回答发表评论;另一种方法是在正在渲染的元素上使用ref属性的回调功能(在组件首次渲染之后):

<input ref={ function(component){ React.findDOMNode(component).focus();} } />

More info

答案 8 :(得分:11)

React 16.3 通过在组件的构造函数中创建引用并按如下所示使用它,添加了一种新的便捷方法来处理此问题:

class MyForm extends Component {
  constructor(props) {
      super(props);

      this.textInput = React.createRef();
  }

  componentDidMount() {
    this.textInput.current.focus(); // one important change here is that we need to access the element via current.
  }

  render() {
    // instead of using arrow function, the created ref can be used directly.
    return(
      <div>
        <input ref={this.textInput} />
      </div>
    );
  }
}

有关更多详细信息,您可以在React博客中查看this article

答案 9 :(得分:11)

这是正确的方法,如何自动对焦。当您使用回调而不是字符串作为ref值时,会自动调用它。您可以使用getDOMNode

获取您的参考,而无需触及DOM
render: function() {
  return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
  this._input.focus();
},

答案 10 :(得分:10)

这不再是最佳答案。自v0.13起,this.refs可能在AF componentDidMount()运行之后才可用,在某些奇怪的情况下。

只需将autoFocus标记添加到输入字段,如上面的FakeRainBrigand所示。

答案 11 :(得分:8)

请注意,material-ui TextField component这些答案都不适用于我。每How to set focus to a materialUI TextField?我必须跳过一些箍才能让它发挥作用:

const focusUsernameInputField = input => {
  if (input) {
    setTimeout(() => {input.focus()}, 100);
  }
};

return (
  <TextField
    hintText="Username"
    floatingLabelText="Username"
    ref={focusUsernameInputField}
  />
);

答案 12 :(得分:8)

您可以将该方法调用放在render函数中。或者在生命周期方法内componentDidUpdate

答案 13 :(得分:7)

你不需要getInputDOMNode ??在这种情况下...

只需在安装组件时获取reffocus() - componentDidMount ...

import React from 'react';
import { render } from 'react-dom';

class myApp extends React.Component {

  componentDidMount() {
    this.nameInput.focus();
  }

  render() {
    return(
      <div>
        <input ref={input => { this.nameInput = input; }} />
      </div>
    );
  }

}

ReactDOM.render(<myApp />, document.getElementById('root'));

答案 14 :(得分:6)

使用带有Typescript的React Hooks /功能组件,您可以将HTMLInputElementuseRef hook用作useRef的通用参数:

import React, { useEffect, useRef } from 'react';

export default function MyComponent(): JSX.Element {
    const inputReference = useRef<HTMLInputElement>(null);

    useEffect(() => {
        inputReference.current?.focus();
    }, []);

    return (
        <div>
            <input ref={inputReference} />
        </div>
    );
}

或者如果使用reactstrap,请向inputReference而不是innerRef提供ref

import React, { useEffect, useRef } from 'react';
import { Input } from 'reactstrap';

export default function MyComponent(): JSX.Element {
    const inputReference = useRef<HTMLInputElement>(null);

    useEffect(() => {
        inputReference.current?.focus();
    }, []);

    return (
        <div>
            <Input innerRef={inputReference} />
        </div>
    );
}

答案 15 :(得分:4)

AutoFocus对我来说效果最好。我需要在双击时将一些文本更改为带有该文本的输入,这就是我最终得到的结果:

<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

答案 16 :(得分:2)

最简单的答案是添加ref =&#34;某些名称&#34;在输入文本元素中调用以下函数。

componentDidMount(){
   this.refs.field_name.focus();
}
// here field_name is ref name.

<input type="text" ref="field_name" />

答案 17 :(得分:2)

我有同样的问题,但我也有一些动画,所以我的同事建议使用window.requestAnimationFrame

这是我元素的ref属性:

ref={(input) => {input && window.requestAnimationFrame(()=>{input.focus()})}}

答案 18 :(得分:2)

  

警告:ReactDOMComponent:不访问DOM节点的.getDOMNode();相反,直接使用节点。此DOM节点由<label class="item item-text-wrap"> <button class="button button-block button-outline button-positive" ng-click="performselectUnit()"> Select Unit </button> {{showSelectedUnit}} </label> 呈现。

应该是

App

答案 19 :(得分:1)

阅读几乎所有答案,但没有看到getRenderedComponent().props.input

设置文本输入参考

this.refs.username.getRenderedComponent().props.input.onChange('');

答案 20 :(得分:1)

尝试了很多上述选项但没有成功后,我发现原来是disabling,然后是enabling,导致焦点丢失的输入。

我有一个道具sendingAnswer,它将在轮询后端时禁用输入。

<Input
  autoFocus={question}
  placeholder={
    gettingQuestion ? 'Loading...' : 'Type your answer here...'
  }
  value={answer}
  onChange={event => dispatch(updateAnswer(event.target.value))}
  type="text"
  autocomplete="off"
  name="answer"
  // disabled={sendingAnswer} <-- Causing focus to be lost.
/>

一旦我移除了禁用的道具,一切都会重新开始。

答案 21 :(得分:1)

要将焦点移至新创建的元素,可以将元素的ID存储在状态中,并使用其设置autoFocus。例如

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(即在更新其他状态时它将不会继续窃取焦点) )。

答案 22 :(得分:1)

根据更新后的语法,您可以使用this.myRref.current.focus()

答案 23 :(得分:1)

<input type="text" autoFocus />

始终先尝试简单且基本的解决方案,对我有用。

答案 24 :(得分:1)

Ben Carp 在打字稿中的解决方案

React 16.8 + 功能组件 - useFocus hook

export const useFocus = (): [React.MutableRefObject<HTMLInputElement>, VoidFunction] => {
  const htmlElRef = React.useRef<HTMLInputElement>(null);
  const setFocus = React.useCallback(() => {
    if (htmlElRef.current) htmlElRef.current.focus();
  }, [htmlElRef]);

  return React.useMemo(() => [htmlElRef, setFocus], [htmlElRef, setFocus]);
};

答案 25 :(得分:0)

您可以查看here

的更新版本
@Test
public void testLogin() throws Exception {
    RequestBuilder requestBuilder = formLogin().user("test@tester.de").password("test");
    mockMvc.perform(requestBuilder).andExpect(redirectedUrl("/home")).andExpect(status().isFound());
    mockMvc.perform(get("/home").with(csrf())).andExpect(status().isOk());
}

答案 26 :(得分:0)

由于造成此错误的原因很多,我认为我也应该发布我面临的问题。对我来说,问题在于我将输入内容作为另一个组件的内容来呈现。

export default ({ Content }) => {
  return (
  <div className="container-fluid main_container">
    <div className="row">
      <div className="col-sm-12 h-100">
        <Content />                                 // I rendered my inputs here
      </div>
    </div>
  </div>
  );
}

这就是我调用上述组件的方式:

<Component Content={() => {
  return (
    <input type="text"/>
  );
}} />

答案 27 :(得分:0)

没有自动对焦的简单解决方案:

<input ref={ref => ref && ref.focus()}
    onFocus={(e)=>e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length)}
    />

ref触发焦点,然后触发onFocus计算结束点并相应地设置光标。