コンポーネントがレンダリングされた後に特定のテキストフィールドにフォーカスを設定するための反応的な方法は何ですか?
ドキュメンテーションは参照の使用を提案するようです、例えば:
Render関数の入力フィールドにref="nameInput"
を設定してから、以下を呼び出します。
this.refs.nameInput.getInputDOMNode().focus();
しかし、私はこれをどこに呼ぶべきですか?私はいくつかの場所を試してみましたが、私はそれを機能させることができません。
代わりに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>
@ Dhirajの答えは正しいです、そして便利のためにあなたはマウントされたとき入力に自動的に焦点を合わせるようにautoFocus支柱を使うことができます:
<input autoFocus name=...
Jsxでは、大文字と小文字を区別しない通常のhtmlとは異なり、autoFocus
(大文字のF)です。
React 0.15 の時点では、最も簡潔な方法は次のとおりです。
<input ref={input => input && input.focus()}/>
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
この問題に遭遇したばかりで、reactを使用しています 15.0.1 15.0.2と私はES6の構文を使用していて、v.15が数週間前に削除され、 this.refs
プロパティのいくつかが廃止されて と removed になったので、他の答えから必要なものを得られませんでした。
概して、私が必要としていたのは、
私が使っている:
ページの最初のautoFocus={true}
に<input />
を使用したので、コンポーネントがマウントされたときにフォーカスが得られます。
これにはもっと時間がかかり、より複雑になりました。簡潔にするために、ソリューションに関連しないコードは避けています。
フォーカスを設定する必要があるかどうかを確認し、設定されたときに無効にするグローバル状態が必要です。そのため、コンポーネントが再レンダリングされるときにフォーカスを再設定し続けません(フォーカスの確認に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()
メソッドの中で呼び出しました。
乾杯!
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は、フォーカスを次のフィールド要素に移動します。
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();
}
}} />
);
},
これが正しい方法です、オートフォーカスする方法です。参照値としてstringの代わりにコールバックを使用すると、自動的に呼び出されます。 getDOMNode
を使ってDOMに触れる必要なしにあなたのrefを利用できるようになりました
render: function() {
return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
this._input.focus();
},
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ブログで この記事 をチェックしてください。
参考文献@ Dhirajの回答に対する@ Daveのコメント。別の方法は、(コンポーネントが最初にレンダリングした後に)レンダリングされる要素のref属性のコールバック機能を使用することです。
<input ref={ function(component){ React.findDOMNode(component).focus();} } />
これはもはや最善の解決策ではありません。 v0.13以降、this.refs
はcomponentDidMount()
が実行されるまで利用できない場合があります(奇妙な場合もあります)。
FakeRainBrigandが上に示したように、入力フィールドにautoFocus
タグを追加するだけです。
そのメソッド呼び出しをrender関数の中に入れることができます。あるいはライフサイクルメソッドの中では、componentDidUpdate
material-ui TextFieldコンポーネント を使っても、これらの答えはどれも私にとっては役に立ちませんでした。 Per どのようにmaterialUI TextFieldにフォーカスを設定するのですか? 私はこれを機能させるためにいくつかのフープを飛び越えなければなりませんでした:
const focusUsernameInputField = input => {
if (input) {
setTimeout(() => {input.focus()}, 100);
}
};
return (
<TextField
hintText="Username"
floatingLabelText="Username"
ref={focusUsernameInputField}
/>
);
getInputDOMNode
は必要ありません。この場合...
コンポーネントがマウントされたときに単にref
とfocus()
を取得する - 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'));
オートフォーカスは私には最適でした。ダブルクリックで、あるテキストをそのテキストを含む入力に変更する必要がありましたので、これが私が最終的に得たものです:
<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
私は同じ問題を抱えていますが、私もアニメーションを持っているので、私の同僚はwindow.requestAnimationFrameを使うことを勧めます
これは私の要素のref属性です:
ref={(input) => {input && window.requestAnimationFrame(()=>{input.focus()})}}
最も簡単な答えは、入力テキスト要素にref = "some name"を追加して下記の関数を呼び出すことです。
componentDidMount(){
this.refs.field_name.focus();
}
// here field_name is ref name.
<input type="text" ref="field_name" />
Warning:ReactDOMComponent:DOMノードの.getDOMNode()にアクセスしないでください。代わりに、ノードを直接使用してください。このDOMノードは
App
によってレンダリングされました。
する必要があります
componentDidMount: function () {
this.refs.nameInput.focus();
}
新しく作成した要素にフォーカスを移動するには、その要素の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
の設定を解除する必要はありません(つまり、他の状態を更新してもフォーカスが奪われ続けることはありません)。
上記の多くのオプションを試しても成功しなかったのですが、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.
/>
無効になったプロップを削除すると、すべてが再び機能し始めました。
ほとんどすべての答えを読みますが、getRenderedComponent().props.input
は見ませんでした
テキスト入力参照を設定します
this.refs.username.getRenderedComponent().props.input.onChange('');
あなたがチェックすることができるアップデート版 ここ
componentDidMount() {
// Focus to the input as html5 autofocus
this.inputRef.focus();
}
render() {
return <input type="text" ref={(input) => { this.inputRef = input }} />
})