レンダリング後に入力フィールドにフォーカスを設定するにはどうすればよいですか?


629

コンポーネントがレンダリングされた後、特定のテキストフィールドにフォーカスを設定する反応的な方法は何ですか?

ドキュメントは参照の使用を提案しているようです、例えば:

ref="nameInput"render関数の入力フィールドに設定してから、次を呼び出します。

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

しかし、これをどこに呼べばいいのでしょうか。私はいくつかの場所を試しましたが、機能させることができません。

回答:


669

代わりにそれを行う必要がcomponentDidMountありrefs callbackます。このようなもの

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

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'));
<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>


107
これは正解ですが、別のボタンがクリックされるまで、コンポーネントは最初に何もレンダリングしないため、私にとってはうまくいきませんでした。つまり、すでにマウントされているため、this.refs.nameInput.getDOMNode()。focus();を追加する必要がありました。componentDidMountの代わりにcomponentDidUpdate内。
Dave

9
element.focus()が呼び出されると、カーソルが入力の先頭に置かれるのはなぜですか?私はこのバグを私のアプリ、Chrome、実際には<textarea>で確認しましたが、ここでデモを確認すると同じです。
davnicwil 2015年

15
警告:React.findDOMNodeは非推奨になっています。代わりにrequire( 'react-dom')のReactDOM.findDOMNodeを使用してください。
アンドレ・ペーニャ

5
@HuwDaviesは、私はあなたが使用してそれを行うだろうと推測refのコールバック属性<input>要素を。何か<input ref={ (component) => ReactDOM.findDOMNode(component).focus() } />
ヘルマン

5
なぜ ref = {(input)=> {input.focus()}}を使用し ないのですか?このソリューションは私にとってはうまくいきます。
HCLiu 2018

841

@Dhirajの答えは正しいです。便宜上、autoFocusプロップを使用して、マウント時に入力を自動的にフォーカスすることができます。

<input autoFocus name=...

jsxでは、大文字とautoFocus小文字を区別しないプレーンな古いhtmlとは異なり、(大文字のF)であることに注意してください。


95
なお、JSXその自動でF大文字と小文字を区別しないで、昔ながらのHTMLとは異なり、ocus(資本F)。
prauchfuss 2015年

8
非常に良い、長い実りのない検索の後にここに来ました:)参考までに、私はReact.DOM.input({type: 'text'、defaultValue:content、autoFocus:true、onFocus:function(e){e.target。 select();}})
mlo55 '20

4
autoFocusは最初のページのレンダリングでのみ機能することがわかりました。codepen.io/ericandrewlewis/pen/PbgwqJ?editors=1111を参照して、3秒後に入力にフォーカスする必要があります。
エリックアンドリュールイス

45
このメソッドの+1。これはautofocus、HTML5の信頼性の低い属性を使用するだけでなく、実際にDOMマウントで使用focus()するreact-domため、非常に信頼性が高いことに言及する価値があります。
アーロンベア2017年

3
「便宜上」だけでなく、コンポーネントが機能コンポーネントの場合も同様です。
phillyslick

167

React 0.15以降、最も簡潔な方法は次のとおりです。

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

5
これは最初のレンダリング以外のシナリオも処理しますが、autoFocusを使用するだけでは処理されません。
Matt Stannett 2017年

質問、入力がfalseになるのはいつですか?アロー関数内の式を参照しています。
JaeGeeTee

2
@JaeGeeTeeコンポーネントがマウントされるまで、および/またはコンポーネントがアンマウントされた後はnullです(どちらに該当するかは覚えていません)。
イリヤセメノフ2018年

12
これで唯一の問題は、それがどんな再レンダリング希望されない場合がありますどの入力を焦点を当てていること..です
ヤロスラフBenc

私の場合は機能しません(Ant Design入力コンポーネントを使用)
vsync

118

マウントを重視

マウント(最初のレンダリング)時に要素にフォーカスを設定するだけの場合は、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} 
}

完全なデモ


2
この回答には、React Hooksの正しいアプローチが含まれています。素晴らしい!TypeScriptの型チェックはそのままではありませんが、それを機能させる1つの(醜い)方法です:配列の代わりに(1)(htmlElRef.current as any).focus()と(2)return {htmlElRef, setFocus}
Ahmed Fasih

@AhmedFasih、私はあなたが言っていることを知っていますが、このスレッドの範囲外だと思います。オブジェクトを返すと、変数の名前を制御することが難しくなります。これはuseFocus、複数の要素に使用する場合に問題になる可能性があります。
ベン・カープ

8
ここはuseFocusTypescript で書かれています。gist.github.com/carpben/de968e377cbac0ffbdefe1ab56237573
ベン・カープ

2
超ジューシー、ありがとう!!! うわー、私はconstアサーション(as constあなたが持っている)については知りませんでした。
Ahmed Fasih

@BenCarpフックの小さな提案setは、を2番目の位置に置く方が良いかもしれませんconst [inputRef, setInputFocus] = useFocus()。これは、useStateにさらに一致します。最初にオブジェクト、次にそのオブジェクトのセッター
Rubanov

59

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


9
そして、それを大文字にすることを忘れないでFください!(回答者ではなく、自分自身と他の人への注意)。
2540625

29

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ブログでこの記事を確認してください

更新:

React 16.8以降では、useRefフックを関数コンポーネントで使用して同じ結果を得ることができます。

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

const MyForm = () => {
  const textInput = useRef(null);

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

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

26

私はこの問題に遭遇し、react 15.0.1 15.0.2を使用していて、ES6構文を使用していて、v.15が数週間前にドロップされたため、他の回答から必要なものといくつかのthis.refsプロパティを取得できませんでした非推奨された取り外し

一般的に、私が必要としたのは:

  1. コンポーネントのマウント時に最初の入力(フィールド)要素にフォーカスします
  2. エラーのある最初の入力(フィールド)要素にフォーカスします(送信後)。

私が使用しています:

  • Reactコンテナー/プレゼンテーションコンポーネント
  • 戻ってきた
  • リアクトルーター

最初の入力要素にフォーカス

ページautoFocus={true}の最初の部分<input />で使用したので、コンポーネントがマウントされるとフォーカスされます。

エラーのある最初の入力要素にフォーカスする

これには時間がかかり、より複雑でした。簡潔にするために、ソリューションに関係のないコードは除外しています。

Redux Store / State

フォーカスを設定する必要があるかどうかを確認し、設定時に無効にするために、グローバル状態が必要です。そのため、コンポーネントが再レンダリングされるときにフォーカスを再設定し続けません(componentDidUpdate()フォーカスの設定を確認するために使用します)。 )

これは、アプリケーションに適するように設計できます。

{
    form: {
        resetFocus: false,
    }
}

コンテナコンポーネント

コンポーネントがresetfocus自分自身にフォーカスを設定することになった場合、コンポーネントはプロパティを設定し、プロパティをクリアするためにcallBack を持つ必要があります。

また、主にプロジェクトがかなり大きいため、アクションクリエーターを個別のファイルに整理しました。それらをより扱いやすいチャンクに分割したかったのです。

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 に設定する必要があります。次に、各コンポーネントが自身を更新するときに、フォーカスを取得したかどうかを確認する必要があることを確認し、取得した場合は、イベントをディスパッチしてフォーカスをリセットします。

編集 補足として、私はビジネスロジックを「ユーティリティ」ファイルに入れ、メソッドをエクスポートして、各shouldfocus()メソッド内で呼び出しました。

乾杯!


25

Reactのドキュメントには、これに関するセクションがあります。https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute

 render: function() {
  return (
    <TextInput
      ref={function(input) {
        if (input != null) {
          input.focus();
        }
      }} />
    );
  },

1
これは、この特定のシナリオでそれを行うには良い方法だと思います。
fabio.sussetto 2016年

autofocusマウントする必要はありませんでした。値を入力するときに、要素が引き続きフォーカスされるように探していました。これはそのシナリオでは完全に機能しました。(react 15を使用)
Matt Parrilla 2016年

13

これはもはや最良の答えではありません。v0.13以降、いくつかの奇妙なケースでは、this.refsAFTER componentDidMount()が実行されるまで使用できない場合があります。

autoFocusFakeRainBrigandが上記で示したように、タグを入力フィールドに追加するだけです。


4
複数の<input autofocus>フィールドが
適切に

4
もちろん違います。ページごとに1つのフォーカスのみ。複数のオートフォーカスがある場合は、コードと意図を確認する必要があります。
GAEfan 2015年

2
<input>
@Dave

1
オートフォーカスで、iOSキーボードを強制的に開く方法はありますか?
Remi Sture

1
@RemiSture同じ質問。誰かがこの問題の解決策を持っていますか?
NamLêQuý19年

12

参照 @Dhirajの回答に対する@Daveのコメント。代替方法は、(コンポーネントが最初にレンダリングされた後)レンダリングされる要素のref属性のコールバック機能を使用することです。

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

より詳しい情報


私がこれを試したとき、私は得ました:Uncaught TypeError: Cannot read property 'focus' of null
reectrix

1
パラメータをnullチェックする必要があります。コンポーネントがマウントされていない場合はnullになります。簡単component && React.findDomNode...です。ここではそれについての詳細を読む:facebook.github.io/react/docs/...
パーWiklander

12

これは適切な方法であり、オートフォーカスの方法です。文字列の代わりにコールバックを参照値として使用すると、それは自動的に呼び出されます。を使用してDOMに触れる必要がない場合よりも、参照を利用できます。getDOMNode

render: function() {
  return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
  this._input.focus();
},

2
コントロールされたフォームはどうですか?
ピクセル67

@ pixel67また。要素だけでなくコンポーネントにも参照を設定できます。しかし、それを扱うときは、そのことを知っておく必要があります。したがって、React.Componentに参照を設定すると、html入力をラップするため、入力の.valueにアクセスしようとはしません。
Pavel Hasala 2017

10

これらの回答はいずれも、material-ui TextFieldコンポーネントでは機能しませんでした。あたりはどのようmaterialUIのTextFieldにフォーカスを設定しますか?私はこれを機能させるためにいくつかのフープを飛び越えなければなりませんでした:

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

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

2
コンポーネントがアニメーション化されている場合、アニメーションfocus()の終了までへの呼び出しを遅らせる必要があるようです。
adriendenat 2017

9

そのメソッド呼び出しをrender関数内に置くことができます。またはライフサイクルメソッド内で、componentDidUpdate


1
componentDidUpdateは、私の場合にうまくいきました。renderが呼び出された後、特定のボタンにフォーカスを設定する必要がありました。
FariaC 2015

8

あなたは必要ありません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'));

5

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


3

同じ問題がありますが、アニメーションもいくつかあるので、同僚はwindow.requestAnimationFrameを使用することを提案しています

これは私の要素のref属性です:

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

2

警告:ReactDOMComponent:DOMノードの.getDOMNode()にはアクセスしないでください。代わりに、ノードを直接使用してください。このDOMノードはによってレンダリングされましたApp

する必要があります

componentDidMount: function () {
  this.refs.nameInput.focus();
}

2

最も簡単な答えは、入力テキスト要素にref = "some name"を追加して、以下の関数を呼び出すことです。

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

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

2

新しく作成された要素にフォーカスを移動するには、要素の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(つまり、他の状態を更新するときにフォーカスを奪い続けることはありません)。


1

ほぼすべての答えを読んだが、見なかった getRenderedComponent().props.input

テキスト入力参照を設定する

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


彼らのコードの文脈であなたの答えをさらに明確にしてください。
ジミースミス

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.
/>

無効にしたプロップを削除すると、すべてが再び機能し始めました。


0

ここで確認できる更新バージョン

componentDidMount() {

    // Focus to the input as html5 autofocus
    this.inputRef.focus();

}
render() {
    return <input type="text" ref={(input) => { this.inputRef = input }} />
})

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"/>
  );
}} />

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.