wake-up-neo.net

Warum verliert das Eingabefeld nach dem Eingeben eines Zeichens den Fokus in React ES6?

In meiner Komponente unten verliert das Eingabefeld nach Eingabe eines Zeichens den Fokus. Bei der Verwendung des Inspectors von Chrome sieht es so aus, als würde das gesamte Formular beim Eingeben anstelle des value-Attributs des Eingabefelds erneut dargestellt werden.

Ich bekomme weder von eslint noch von Chrome Inspector eine Fehlermeldung.

Das Senden des Formulars selbst funktioniert genauso wie das eigentliche Eingabefeld, wenn es sich entweder in der Rückgabe des Renderers befindet oder als separate Komponente importiert wird, jedoch nicht so, wie ich es unten codiert habe.

Warum ist das so?

Hauptseite Komponente

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);

Texteingabekomponente

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;

Schaltfläche "Senden"

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;
8
spunge

Was passiert, ist folgendes:

Wenn Ihr onChange-Ereignis ausgelöst wird, ruft der Rückruf setState mit dem neuen Titelwert auf, der als Requisite an Ihr Textfeld übergeben wird. An diesem Punkt wird es von React erneut angezeigt, weshalb Sie den Fokus verlieren.

Mein erster Vorschlag wäre, die Schlüssel Ihrer Komponenten anzugeben, insbesondere das Formular und die Eingabe selbst. Mithilfe von Schlüsseln kann React die Identität von Komponenten durch Rendern beibehalten.

6
Ezra Chang

Ich bin neu in React und bin auf dieses Problem gestoßen.

Folgendes habe ich getan, um zu lösen:

  1. Verschieben Sie zuerst alle Ihre Komponenten in Ihren Komponentenordner und importieren Sie sie dann dort, wo Sie sie verwenden möchten
  2. Stellen Sie sicher, dass alle Formularelemente die Eigenschaften name und id erhalten
  3. Stellen Sie sicher, dass alle Komponenten, wenn Sie den Baum hinaufgehen, ein eindeutiges key erhalten.

Jemand, der schlauer als ich ist, kann uns wahrscheinlich sagen, warum wir Schritt eins überspringen und sozusagen alles inline halten können, aber das hat mir nur dabei geholfen, den Code zu organisieren.

Ich denke, das eigentliche Problem ist React rendert alles (wie bereits erwähnt) und manchmal geschieht das Rendering auf einer übergeordneten Komponente, die kein key hat, aber eines benötigt.

Mein Problem bestand darin, dass ExpansionPanel Komponenten meine benutzerdefinierten Komponenten für Formulareingaben umschlossen. Die Panels brauchten auch key!

Hoffe das hilft jemand anderem da draußen, das hat mich verrückt gemacht!

1
Nateous

Ihr Formular wird beim Eingeben eines Zeichens erneut gerendert, da Sie über eine onChange -Methode verfügen, die den Status ändert. Bei jeder Statusänderung wird das Formular erneut gerendert, weshalb die Eingabemethode den Fokus verliert.

Da Sie Redux verwenden, ist es am besten, den Post-Titelwert im Redux-Objekt zu speichern. Vielleicht möchten Sie auch redux-form für Ihr Formular.

So erhalten Sie den Wert der Eingabe ohne re-rendering Sie müssen refs verwenden.

dies liegt daran, dass Sie das Formular in einer Funktion in render () rendern.

Jedes Mal, wenn sich Ihr Status/Ihre Eigenschaft ändert, gibt die Funktion ein neues Formular zurück. Sie haben den Fokus verloren.

Versuchen Sie, das, was sich in der Funktion befindet, direkt in Ihren Renderer einzufügen.

       <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>
0
Alex Yan

Ich darf nicht kommentieren, dann muss es eine Antwort sein. Ich hatte ein ähnliches Problem und die Antwort von Alex Yan war korrekt.

Ich hatte nämlich diese Funktion 

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>)}))}

das verhält sich mit FF in Ordnung und nicht mit Chrome, wenn es als <DisplaySearchArea />.__ gerendert wird. Wenn es als {...} gerendert wird, ist es mit beiden in Ordnung. Das ist zwar nicht so "seltsam" aussehender Code, aber es wurde bereits gesagt, dass ich die Tendenz habe, Lambdas zu überfordern.

0

Mein Problem war das erneute Rendern in einer zustandslosen Komponente in derselben Datei. Nachdem ich diese unnotwendige zustandslose Komponente entfernt und den Code direkt eingefügt hatte, hatte ich keine unnötigen Renderer mehr

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>
0