2017-03-03 28 views
5

以下のコンポーネントでは、文字を入力した後に入力フィールドのフォーカスが失われます。 Chromeのインスペクタを使用しているときは、入力時に入力フィールドのvalue属性だけでなく、フォーム全体が再描画されているように見えます。React ES6では、文字を入力した後に入力フィールドがフォーカスを失うのはなぜですか?

私は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; 

答えて

0

状態を変更するonChangeメソッドがあるため、文字を入力するとフォームが再表示されます。すべての状態の変更によってフォームが再レンダリングされるため、入力メソッドがフォーカスを失っているのはこのためです。

reduxを使用しているので、最も良い方法は、投稿タイトルの値をreduxオブジェクトに保存することです。また、フォームにredux-formを使用して見たい場合もあります。

re-renderingのない入力値を取得するには、refsを使用する必要があります。何が起こっている

2

はこれです:

すると、あなたのonChangeイベント火災、コールバックは小道具としてあなたのテキストフィールドに渡される新しいタイトル値、とSETSTATEを呼び出します。その時点で、Reactはそれを新たにレンダリングします。そのため、フォーカスを失うのです。

私の最初の提案は、コンポーネントキー、特にフォームと入力そのものを提供することです。キーは、Reactがレンダリングを通してコンポーネントのアイデンティティを保持できるようにします。

-1

これは、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> 
関連する問題