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;
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.
Ich bin neu in React und bin auf dieses Problem gestoßen.
Folgendes habe ich getan, um zu lösen:
name
und id
erhaltenkey
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!
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>
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.
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>