Ich versuche, eine Todo-App in reaktiven nativen Funktionen wie addTodo, removeTodo, markCompleted Todo zu implementieren. Nach dem Hinzufügen von Todos, wenn ich markComplete Text drücke, wird das listView nicht neu gerendert, wenn ich die App neu lade zeigt es die erwarteten Ergebnisse an. Ich verwende Firebase-Datenbank, um meine Todos zu holen.ListView wird nicht neu gerendert, nachdem dataSource aktualisiert wurde
Grundsätzlich aktualisiere ich eine Eigenschaft in meiner ListView-Datenquelle, wenn ich auf markComplete klicke. Alles funktioniert einwandfrei. Ich erwarte das erneute Rendern von listView immer dann, wenn ich die Schaltflächen "MarkComplete" oder "Completed" auf der Benutzeroberfläche drücke. Ich habe versucht ein paar Lösungen in verwandten Fragen vorgeschlagen, ich könnte es nicht funktionieren.
Um genauer zu sein: Bitte sehen Sie sich den Code unter Kommentar // Wenn ein Todo geändert wird. Ich aktualisiere meine Datenquelle in diesen Codezeilen, wenn ich etwas im Elementarray ändere.
Unten ist mein Code und Snapshot der App UI.
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
ListView,
Text,
View,
TouchableHighlight,
TextInput
} from 'react-native';
var Firebase = require('firebase');
class todoApp extends Component{
constructor(props) {
super(props);
var myFirebaseRef = new Firebase('[![enter image description here][1]][1]database URL');
this.itemsRef = myFirebaseRef.child('items');
this.state = {
newTodo: '',
completed: false,
todoSource: new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2})
};
this.handleKey = null;
this.items = [];
} // End of Constructor
componentDidMount() {
// When a todo is added
this.itemsRef.on('child_added', (dataSnapshot) => {
this.items.push({
id: dataSnapshot.key(),
text: dataSnapshot.child("todo").val(),
completedTodo: dataSnapshot.child("completedTodo").val()
});
this.setState({
todoSource: this.state.todoSource.cloneWithRows(this.items)
});
});
// When a todo is removed
this.itemsRef.on('child_removed', (dataSnapshot) => {
this.items = this.items.filter((x) => x.id !== dataSnapshot.key());
this.setState({
todoSource: this.state.todoSource.cloneWithRows(this.items)
});
});
// When a todo is changed
this.itemsRef.on('child_changed', (dataSnapshot) => {
this.items.forEach(function (value) {
if(value["id"] == this.handleKey){
this.items["value"]["completedTodo"]= dataSnapshot.child("completedTodo").val()
}
});
this.setState({
todoSource: this.state.todoSource.cloneWithRows(this.items)
});
});
}
addTodo() {
if (this.state.newTodo !== '') {
this.itemsRef.push({
todo: this.state.newTodo,
completedTodo: this.state.completed,
});
this.setState({
newTodo : ''
});
}
console.log(this.items);
}
removeTodo(rowData) {
this.itemsRef.child(rowData.id).remove();
}
handleCompleted(rowData){
this.handleKey = rowData.id;
if(rowData.completedTodo){
this.itemsRef.child(rowData.id).update({
completedTodo: false
})
}
if(rowData.completedTodo == false){
this.itemsRef.child(rowData.id).update({
completedTodo: true
})
}
}
renderRow(rowData) {
return (
<View>
<View style={styles.row}>
<TouchableHighlight
underlayColor='#dddddd'
onPress={() => this.removeTodo(rowData)}>
<Text style={styles.todoText}>{rowData.text}</Text>
</TouchableHighlight>
<TouchableHighlight underlayColor='#dddddd' onPress={() => this.handleCompleted(rowData)}>
{rowData.completedTodo? <Text style={styles.todoText}>Completed</Text>:<Text style={styles.todoText}>MarkCompleted</Text>}
</TouchableHighlight>
</View>
<View style={styles.separator} />
</View>
);
}
render() {
return (
<View style={styles.appContainer}>
<View style={styles.titleView}>
<Text style={styles.titleText}>
My Todos
</Text>
</View>
<View style={styles.inputcontainer}>
<TextInput style={styles.input} onChangeText={(text) => this.setState({newTodo: text})} value={this.state.newTodo}/>
<TouchableHighlight
style={styles.button}
onPress={() => this.addTodo()}
underlayColor='#dddddd'>
<Text style={styles.btnText}>Add!</Text>
</TouchableHighlight>
</View>
<ListView
dataSource={this.state.todoSource}
renderRow={this.renderRow.bind(this)} />
</View>
);
}
} // Main Class End
Ich habe diesen Code vor dem Posten dieser Frage versucht, hat nicht für mich arbeiten. Ich lese es funktioniert, wenn Sie Array haben, aber für Array von Objekten muss es etwas anderes sein. Wenn Sie einen hilfreichen Code zur Verfügung stellen können, wird das großartig. – Sameer
Ich habe immer noch Probleme mit diesem ListView-Problem beim erneuten Rendern. Ich habe viel mehr Lösungen ausprobiert, die in anderen Posts in stackoverflow vorgeschlagen wurden. Gibt es jemanden, der darauf hinweisen kann, was in diesem Code falsch ist? – Sameer