web-dev-qa-db-ja.com

レンダリング後に入力にフォームを設定

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

ドキュメンテーションは参照の使用を提案するようです、例えば:

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

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

しかし、私はこれをどこに呼ぶべきですか?私はいくつかの場所を試してみましたが、私はそれを機能させることができません。

470
Dave

代わりにcomponentDidMountrefs 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>
526
Dhiraj

@ Dhirajの答えは正しいです、そして便利のためにあなたはマウントされたとき入力に自動的に焦点を合わせるようにautoFocus支柱を使うことができます:

<input autoFocus name=...

Jsxでは、大文字と小文字を区別しない通常のhtmlとは異なり、autoFocus(大文字のF)です。

676
FakeRainBrigand

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

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

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

51
Jack Lee

この問題に遭遇したばかりで、reactを使用しています 15.0.1 15.0.2と私はES6の構文を使用していて、v.15が数週間前に削除され、 this.refsプロパティのいくつかが廃止されてremoved になったので、他の答えから必要なものを得られませんでした。

概して、私が必要としていたのは、

  1. コンポーネントがマウントされたときに最初のinput(field)要素をフォーカスします
  2. 最初のinput(field)要素をエラーでフォーカスします(送信後)

私が使っている:

  • リアクトコンテナ/プレゼンテーションコンポーネント
  • リダックス
  • React-Router

最初の入力要素をフォーカスする

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

最初の入力要素をエラーで絞り込む

これにはもっと時間がかかり、より複雑になりました。簡潔にするために、ソリューションに関連しないコードは避けています。

Reduxストア/州

フォーカスを設定する必要があるかどうかを確認し、設定されたときに無効にするグローバル状態が必要です。そのため、コンポーネントが再レンダリングされるときにフォーカスを再設定し続けません(フォーカスの確認に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に設定する必要があります。それから各コンポーネントがそれ自身を更新するとき、それはそれがフォーカスを取得するかどうか確認するためにチェックするべきであることを見るでしょう、そしてフォーカスをリセットするためにイベントを送出するので他の要素はチェックし続ける必要はありません。

edit 付記として、私は自分のビジネスロジックを "utilities"ファイルの中に持っていて、そのメソッドをエクスポートしてそれを各shouldfocus()メソッドの中で呼び出しました。

乾杯!

25
jmbertucci

Refを使う必要はありません

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

例1 - ボタンをクリックすると入力がフォーカスされ、3文字入力するとデフォーカスします。 例2 - enterは、フォーカスを次のフィールド要素に移動します。

24
Ben Carp

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();
        }
      }} />
    );
  },
23
Kevin Suttle

これが正しい方法です、オートフォーカスする方法です。参照値としてstringの代わりにコールバックを使用すると、自動的に呼び出されます。 getDOMNodeを使ってDOMに触れる必要なしにあなたのrefを利用できるようになりました

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

React 16.3 はコンポーネントのコンストラクタにrefを作成して以下のように使うことでこれを処理するための新しい便利な方法を追加しました:

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ブログで この記事 をチェックしてください。

10
ettanany

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

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

詳細情報

10
o01

これはもはや最善の解決策ではありません。 v0.13以降、this.refscomponentDidMount()が実行されるまで利用できない場合があります(奇妙な場合もあります)。

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

10
GAEfan

そのメソッド呼び出しをrender関数の中に入れることができます。あるいはライフサイクルメソッドの中では、componentDidUpdate

8
Raza Gill

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

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

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

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

オートフォーカスは私には最適でした。ダブルクリックで、あるテキストをそのテキストを含む入力に変更する必要がありましたので、これが私が最終的に得たものです:

<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

4
Luke Watts

私は同じ問題を抱えていますが、私もアニメーションを持っているので、私の同僚はwindow.requestAnimationFrameを使うことを勧めます

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

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

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

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

<input type="text" ref="field_name" />
2
Venkatesh Somu

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

する必要があります

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

新しく作成した要素にフォーカスを移動するには、その要素の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
mpen

上記の多くのオプションを試しても成功しなかったのですが、disabling、そしてenablingが入力を喪失する原因となったのと同じことです。

バックエンドをポーリングしている間はInputを無効にするprop 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.
/>

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

1
Jack

ほとんどすべての答えを読みますが、getRenderedComponent().props.inputは見ませんでした

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

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

1
nichery

あなたがチェックすることができるアップデート版 ここ

componentDidMount() {

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

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