在React ES6中,为什么输入字段在输入字符后会失去焦点?

问题描述 投票:12回答:6

在下面的组件中,输入字段在输入字符后失去焦点。在使用Chrome的Inspector时,看起来整个表单正在重新呈现,而不是在输入时仅输入字段的value属性。

我从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;
reactjs text input ecmascript-6 focus
6个回答
8
投票

这是怎么回事:

触发onChange事件时,回调将使用新标题值调用setState,该标题值将作为prop传递给您的文本字段。那时,React重新渲染它,这就是你失去焦点的原因。

我的第一个建议是提供组件键,特别是表单和输入本身。密钥允许React通过渲染保留组件的标识。

编辑:

有关密钥,请参阅此文档:https://reactjs.org/docs/lists-and-keys.html#keys


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>

1
投票

我的问题是它在同一个文件中的无状态组件中重新渲染。所以,一旦我摆脱了那个不必要的无状态组件并直接放入代码,我就没有必要的重新渲染

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>

1
投票

我是React的新手,并且一直在遇到这个问题。

这就是我要解决的问题:

  1. 首先将所有组件移动到组件文件夹中,然后将它们导入到要使用它们的位置
  2. 确保所有表单元素都获得nameid属性
  3. 当你走在树上时,确保所有组件都有一个独特的key

比我更聪明的人可能会告诉我们为什么我们可以跳过第一步并保持内联所有内容,但这只是帮助我组织代码。

我认为真正的问题是React正在重新渲染所有内容(如前所述),有时重新渲染发生在没有key但需要一个的父组件上。

我的问题是ExpansionPanel组件包装我的自定义组件的表单输入。面板也需要key

希望这有助于其他人,这让我发疯!


0
投票

当您输入字符时,您的表单会被重新呈现,因为您有一个onChange方法,它会更改状态。每次状态更改都会导致表单重新呈现,这就是输入方法失去焦点的原因。

由于您使用的是redux,最好的方法是将post title值存储在redux对象中。此外,您可能希望看一下使用redux-form表单。

要获得没有re-rendering的输入值,您需要使用refs


0
投票

我无权发表评论然后必须回答。我有类似的问题,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>)}))}

渲染为<DisplaySearchArea />时,使用FF表现良好而不是使用Chrome。当渲染为{...}时,两者都可以。这不是那么'看起来'代码但工作,我已经被告知有过度使用lambdas的倾向。

© www.soinside.com 2019 - 2024. All rights reserved.