Von Haus aus kann React nur One-Way-Databinding, d.h. das Update des Models muss manuell vorgenommen werden (typischweise per onChange-Handler).
Gerade bei größeren Formularen, bei denen das Datenmodell 1:1 auch persistiert wird, entsteht dadurch viel Boiler-Plate-Code.
Ich stelle hier ein Beispiel für eine Eingabekomponente mit Two-Way-Databinding vor, die automatisch das Modell updated. Bei einem Update des Modells in der Parent-Komponente (z.B. nach dem Laden der Daten) wird die Referenz innerhalb der Komponente aktualisiert.
class LabeledInput extends Component {
constructor(props) {
super(props);
this.state = { value: props.value };
this.id = props.id;
if (!this.state.value[this.id]) {
this.state.value[this.id] = "";
}
this.handleChange = this.handleChange.bind(this);
this.label = props.label;
this.size = props.size ?? 40;
this.styleClass = props.styleClass;
}
handleChange(e) {
this.state.value[this.id] = e.target.value;
this.setState({});
}
static getDerivedStateFromProps(props, state) {
if (props.value !== state.value) {
return {value: props.value};
}
return null;
}
render() {
return (
<div className={this.styleClass + " p-field"}>
<label htmlFor={this.state.value.id + this.id} className="p-d-block">{this.label}</label>
<input type="text" id={this.state.value.id + this.id} className="p-d-block" size={this.size}
value={this.state.value[this.id]} onChange={this.handleChange} />
</div>);
}
}
Verwendet werden kann die Komponente wie folgt:
export class CustomerPage extends Component {
constructor(props) {
super(props);
this.state = { model: { } };
this.persist = this.persist.bind(this);
}
componentDidMount() {
axios.get('/customer')
.then(response => response.data)
.then(model=> this.setState({ model}));
}
persist(e) {
axios.post('/customer', this.state.model);
}
render(){
return (
<div>
<LabeledInput id="name" label="Name" value={this.state.model}
/>
<LabeledInput id="email" label="E-Mail-Adresse" value={this.state.model}
/>
<LabeledInput id="telefon" label="Telefonnummer" value={this.state.model}
/>
<button onClick={this.persist}>Speichern</button>
</div>);
}
}
Schreibe einen Kommentar