以下の私のコンポーネントでは、入力フィールドは文字を入力した後にフォーカスを失います。 Chromeのインスペクターを使用していると、入力時に入力フィールドの値属性だけではなく、フォーム全体が再レンダリングされているように見えます。
EslintとChrome Inspectorのどちらからもエラーは発生しません。
フォーム自体を送信することは、レンダリングのリターンにある場合、または別のコンポーネントとしてインポートされている間に実際の入力フィールドと同じように機能しますが、以下のコーディング方法では機能しません。
これはなぜですか?
メインページコンポーネント
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionPost from '../redux/action/actionPost';
import InputText from './form/InputText';
import InputSubmit from './form/InputSubmit';
class _PostSingle extends Component {
constructor(props, context) {
super(props, context);
this.state = {
post: {
title: '',
},
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(event) {
this.setState({
post: {
title: event.target.value,
},
});
}
onSubmit(event) {
event.preventDefault();
this.props.actions.postCreate(this.state.post);
this.setState({
post: {
title: '',
},
});
}
render() {
const onChange = this.onChange;
const onSubmit = this.onSubmit;
const valueTitle = this.state.post.title;
const FormPostSingle = () => (
<form onSubmit={onSubmit}>
<InputText name="title" label="Title" placeholder="Enter a title" onChange={onChange} value={valueTitle} />
<InputSubmit name="Save" />
</form>
);
return (
<main id="main" role="main">
<div className="container-fluid">
<FormPostSingle />
</div>
</main>
);
}
}
_PostSingle.propTypes = {
actions: PropTypes.objectOf(PropTypes.func).isRequired,
};
function mapStateToProps(state) {
return {
posts: state.posts,
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(actionPost, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(_PostSingle);
テキスト入力コンポーネント
import React, { PropTypes } from 'react';
const InputText = ({ name, label, placeholder, onChange, value, error }) => {
const fieldClass = 'form-control input-lg';
let wrapperClass = 'form-group';
if (error && error.length > 0) {
wrapperClass += ' has-error';
}
return (
<div className={wrapperClass}>
<label htmlFor={name} className="sr-only">{label}</label>
<input type="text" id={name} name={name} placeholder={placeholder} onChange={onChange} value={value} className={fieldClass} />
{error &&
<div className="alert alert-danger">{error}</div>
}
</div>
);
};
InputText.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
placeholder: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
value: PropTypes.string,
error: PropTypes.string,
};
InputText.defaultProps = {
value: null,
error: null,
};
export default InputText;
送信ボタンコンポーネント
import React, { PropTypes } from 'react';
const InputSubmit = ({ name }) => {
const fieldClass = 'btn btn-primary btn-lg';
return (
<input type="submit" value={name} className={fieldClass} />
);
};
InputSubmit.propTypes = {
name: PropTypes.string,
};
InputSubmit.defaultProps = {
name: 'Submit',
};
export default InputSubmit;
何が起こっているのですか?
OnChangeイベントが発生すると、コールバックは新しいタイトル値でsetStateを呼び出します。この値は、小道具としてテキストフィールドに渡されます。その時点で、Reactはそれを新たにレンダリングします。これがフォーカスを失う理由です。
私の最初の提案は、コンポーネントのキー、特にフォームと入力自体を提供することです。キーはReact=を介してコンポーネントのアイデンティティを保持することを許可します。
編集:
キーに関するこのドキュメントを参照してください: https://reactjs.org/docs/lists-and-keys.html#keys
私はReactが初めてで、この問題に直面しています。
これが私が解決するためにしたことです:
name
およびid
プロパティを取得するようにしてくださいkey
を取得することを確認してください私よりも賢い人なら、おそらくステップ1をスキップしてすべてをインラインに保つことができる理由を教えてくれるかもしれませんが、これはコードの整理に役立ちました。
本当の問題はReactがすべてを再描画している(既に述べたように)であり、その再描画はkey
を持たないが必要な親コンポーネントで行われることがあると思います。
私の問題は、フォーム入力用のカスタムコンポーネントをラップするExpansionPanel
コンポーネントにありました。パネルにはkey
も必要でした!
これが他の誰かに役立つことを願っています、これは私を夢中にさせていました!
これは、render()内の関数でフォームをレンダリングしているためです。
状態/プロップが変更されるたびに、関数は新しいフォームを返します。それはあなたが焦点を失う原因となりました。
関数内にあるものをレンダリングに直接入れてみてください。
<main id="main" role="main">
<div className="container-fluid">
<FormPostSingle />
</div>
</main>
====>
<main id="main" role="main">
<div className="container-fluid">
<form onSubmit={onSubmit}>
<InputText name="title" label="Title" placeholder="Enter a title" onChange={onChange} value={valueTitle} />
<InputSubmit name="Save" />
</form>
</div>
</main>
私の問題は、同じファイル内のステートレスコンポーネントで再レンダリングすることでした。そのため、不要なステートレスコンポーネントを削除し、コードを直接挿入するだけで、不要な再レンダリングはありませんでした。
render(){
const NewSocialPost = () =>
<div className='new-post'>
<input
onChange={(e) => this.setState({ newSocialPost: e.target.value })}
value={this.state.newSocialPost}/>
<button onClick={() => this._handleNewSocialPost()}>Submit</button>
</div>
return (
<div id='social-post-page'>
<div className='post-column'>
<div className='posts'>
<Stuff />
</div>
<NewSocialPost />
</div>
<MoreStuff />
</div>
状態を変更するonChange
メソッドがあるため、文字を入力するとフォームが再レンダリングされます。状態が変化するたびにフォームが再レンダリングされるため、入力メソッドがフォーカスを失います。
Reduxを使用しているため、最良の方法は投稿タイトルの値をreduxオブジェクトに保存することです。また、フォームで redux-form
を使用することもできます。
re-rendering
なしで入力の値を取得するには、 refs
を使用する必要があります。
私はコメントする権限がありません、それは答えでなければなりません。私は同様の問題を抱えていて、Alex Yanからの回答は共同でした。
つまり、私はその機能を持っていました
const DisplaySearchArea =()=>{return (arrayOfSearchFieldNames.map((element, index)=>{return(<div key ={index} className = {inputFieldStyle}><input placeholder= {arrayOfPlaceholders[index]} type="text" className='border-0'
value={this.state[element]}
onChange={e => {this.setState({ [element]: e.target.value }); console.log(e.target)}}
onMouseEnter={e=>e.target.focus()}/></div>)}))}
Chromeとしてレンダリングされた場合<DisplaySearchArea />
としてではなくFFで問題なく動作します。{...}としてレンダリングされた場合、両方で問題ありません。 、すでにラムダを使いすぎる傾向があると言われています。