2017-03-23 36 views
1

我有以下代碼,導致焦點在公司密碼字段中按下時立即丟失。探索表明該表格正在被重新渲染,作爲setState的結果,但我不知道爲什麼或如何解決。鍵入反應形式輸入會導致焦點丟失並重新呈現

import React from 'react'; 
import LocalizedStrings from 'react-localization'; 

let strings = new LocalizedStrings({ 
    // code omitted 
}); 

class ResetPasswordForm extends React.Component { 

    constructor (props) { 
     super(props); 

     this.state = { 
      key: this.props.key, 
      password: '', 
      passwordConfirm: ''   
     }; 

     this.handleSubmit = this.handleSubmit.bind(this); 
     this.handleChange = this.handleChange.bind(this); 
    } 

    handleChange(event) { 
     this.setState({ 
      [event.target.name]: event.target.value 
     }); 
    } 

    handleSubmit(event) { 
     event.preventDefault(); 

     // TODO 
    } 

    renderField(field) { 
     const name = field.name; 
     const id = field.id || name; 
     const label = strings[name]; 
     const fieldType = field.type || 'text'; 
     const placeholder = strings[name + '-placeholder']; 

     // TODO 
     let touched; 
     let error; 

     return <div className="form-group"> 
      <label htmlFor={id}>{label}:</label> 
      <input id={id} type={fieldType} placeholder={placeholder} name={name} onChange={this.handleChange} 
       value={this.state[name]} 
       className="form-control"/> {touched && error && <div className="error bg-warning">{error}</div>} 
     </div> 
    } 

    render() { 
     const Field = this.renderField.bind(this); 

     return (
      <div> 
      <h2>{strings['title']}</h2> 
      <form onSubmit={this.handleSubmit} > 

       {this.props.statusText && <div className='alert alert-info'> 
        {this.props.statusText} 
       </div>} 

       <Field 
        name="password" 
        type="password" 
        /> 

       <Field 
        name="passwordConfirm" 
        type="password"/> 

       <div className="form-group"> 
        <input 
         type="submit" 
         name="Submit" 
         defaultValue={strings['submit']} 
         /> 
       </div> 

      </form> 
      </div> 
     ) 
    } 
} 

編輯:進一步運行實驗表明,「現場」行導致該問題並用以下替換它們解決了問題:

{this.renderField({ 
    name: "password", 
    type: "password" 
})} 

{this.renderField({ 
    name: "passwordConfirm", 
    type: "password" 
})} 

另外,在構造函數中我可以這樣做:

this.renderField = this.renderField.bind(this); 

然後在渲染功能我可以做:

const Field = this.renderField; 

儘管這些方法有效,但我不確定React更改罪名的確切影響。如果任何人都可以解釋,將不勝感激。

回答

0

我覺得這裏的錯誤:

const Field = this.renderField.bind(this); 

renderField(場)接受對象參數(場)和你永遠傳遞。所以,你需要通過它

const Field = this.renderField.bind(this, { name: "password", type: "password"}); 
+0

這並沒有真正解釋是怎麼回事上。在挖掘中,我發現了兩種替代解決方案(參見問題),但我不確定我是否理解他們爲什麼工作,而不是他們這樣做。 –

0

每次執行render時,你產生新的功能組件與this.renderField.bind(this)。在這種情況下,React的協調算法會將其視爲差異,並且整個子樹將從頭開始渲染。

docs

Elements Of Different Types

Whenever the root elements have different types, React will tear down the old tree and build the new tree from scratch. Going from to , or from to , or from to - any of those will lead to a full rebuild.

這裏是DevTools元件檢查員的擷取畫面,其示出在兩種情況下

  1. 原始(場是在每個所生成的渲染)
    您DOM更新可以看到<div>節點已摺疊並從頭渲染=>焦點丟失。
    enter image description here
  2. 固定this.renderField({...})使用)
    只有"value"字段更新,DOM的其餘部分完好=>焦點保留
    enter image description here
相關問題