输入反应形式输入会导致焦点丢失和重新渲染

时间:2017-03-23 04:39:41

标签: javascript reactjs

我有以下代码,这会导致在公司密码字段中按下键后焦点丢失。由于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的变更罪的确切影响。如果有人能解释,我们将不胜感激。

2 个答案:

答案 0 :(得分:0)

我认为这是错误:

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

renderField(field)接受对象参数(字段),你永远不会传递它。所以你需要传递它

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

答案 1 :(得分:0)

每次执行render时,您都会使用this.renderField.bind(this)生成新的功能组件。在这种情况下,React的协调算法会将此视为差异,整个子树将从头开始呈现。

来自docs

  

不同类型的元素

     

每当根元素具有不同类型时,React将会拆除   旧树并从头开始构建新树。从去到   或者来自,或来自 - 任何   这些将导致完全重建。

这是一个DevTools元素检查器的屏幕截图,它说明了两种情况下的DOM更新

  1. 原始(每个渲染都生成字段)
    您可以看到<div>节点已折叠并从头开始渲染=&gt;焦点丢失。
    enter image description here
  2. 已修复(使用this.renderField({...})
    仅更新"value"字段,其余DOM完整=&gt;重点保留了 enter image description here