2017-11-22 2 views
0

Ich habe zwei Komponenten.React Native: Wie die Elternkomponente von einem Ereignis auf der Kindkomponente neu zu rendern

geordnete Komponente: App.js

Child Komponente: Logitem.js

geordnete Komponente macht eine Liste der untergeordneten Komponenten.

Jede untergeordnete Komponente hat ein Textelement, und wenn das Textelement angeklickt wird, wird ein Modal angezeigt.

Das Modal verfügt über eine Schaltfläche zum Löschen und führt eine Löschoperation aus.

All dies funktioniert gut.

Wenn ich auf die Schaltfläche zum Löschen innerhalb des Modals klicke, setze ich eine boolesche Variable, um das Modal auszublenden, das auch funktioniert.

Die Liste (mit dem Array der untergeordneten Komponenten) ist jedoch nicht die letzte, d. H. Das gelöschte Element wird weiterhin in der Liste angezeigt.

Gibt es Möglichkeiten, die render() Methode der übergeordneten Komponente erneut zu rendern.

Ich habe versucht, den Status der übergeordneten Komponente (count) über die untergeordnete Komponente, aber immer noch kein Glück.

Ich glaubte, dass, wenn der Zustand der Elternkomponente geändert wird die render() der Elternkomponente aufgerufen wird, aber das ist nicht passiert.

Kann mir jemand sagen, was man hier machen kann?

geordnete Komponente

import React, { Component } from 'react'; 
import { StyleSheet, View, Text, ScrollView, Modal, DatePickerIOS } from 'react-native'; 
import { 
    dropLogsTable, 
    createLogsTable, 
    getProfileHeightStandardfromDB, 
    saveLogsRecord, 
    populateDummyLogs, 
    getLogsRecords, 
    getLogsRecordsFromDB, 
    neverendingmethod, 
    getLogsDetailsforSaveDelete 
} from '../src/helper'; 
import { Spinner } from '../src/Spinner'; 
import Logitem from '../src/Logitem'; 

export default class App extends Component { 
    state = { 

    allLogs:{ 
       rows:{ 
          _array:[{logstringdate:''}] 
         } 

      }, 
    profileobject: {profileheight: 100, profilestandard: "XYZ"}, 
    showspinner: true, 
    count:0 


    }; 


    componentDidMount() { 
    this.fetchProfileData(); 
    this.getAllLogs(); 
} 


renderSpinner() { 
    if(this.state.showspinner) { 
    return <Spinner size="small" />; 
    } 
    else { 
    //return this.state.allLogs.rows._array.map(ae => <Text>{ae.bmi}</Text>); 
    return this.state.allLogs.rows._array.map(
    (ae) => (
       <View 
        key={ae.logdate} 
       > 
       <Logitem 

         logstringdate={ae.logstringdate} 
         bmi={ae.bmi} 
         weight={ae.metricweight} 
         logdate={ae.logdate} 
         incrementCount={() => this.setState({count: count+1)} 

         /> 
       </View> 
    ) 

); 

    } 

} 


    async fetchProfileData() { 
    console.log('Before Profile Fetch'); 
    const result = await getProfileHeightStandardfromDB(); 
    console.log('After Profile Fetch'); 
    console.log('Height : '+result.profileheight); 
    console.log('Standard: '+result.profilestandard); 
    this.setState({profileobject:result}); //Line Y 
    return result; //Line X 

    } 

    async getAllLogs() { 
    console.log('Before All Logs Fetch'); 
    const allLogs = await getLogsRecordsFromDB(); 
    console.log('After All Logs Fetch'); 
    console.log('Spinner State ==>'+this.state.showspinner); 
    if(allLogs != null) 
    { 
    this.setState({allLogs, showspinner: false}); 
    console.log('After async spinner state ==>'+this.state.showspinner); 
    console.log(allLogs); 
    } 
    return allLogs; 
    } 


    render() { 
    return (
     <ScrollView style={styles.container}> 
       {this.renderSpinner()} 
     </ScrollView> 
); 


    } 
} 


const styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    }, 
    top: { 
    width: '100%', 
    flex: 1, 
    }, 
    bottom: { 
    flex: 1, 
    alignItems: 'center', 
    }, 
}); 

Kinder Komponente

import React, { Component } from 'react'; 
import { Text, View, Modal, DatePickerIOS, TextInput, Button } from 'react-native'; 
import { 
    deleteSelectedRecordDB 
} from '../src/helper'; 
import { Spinner } from '../src/Spinner'; 


export default class Logitem extends Component { 

    constructor(props) { 
    super(props); 
    const { logstringdate, bmi, weight, logdate } = this.props; 

    } 

state = { 
    selecteddate: '1', 
    selectedweight: this.props.weight, 
    showmodal: false, 
    date: new Date(86400000 * this.props.logdate), 

    } 

    async deleteSelectedRecord(){ 
    console.log('Delete clicked'); 
    console.log('this.state.selecteddate ==>' + this.state.selecteddate); //LINE X 
    const result = await deleteSelectedRecordDB(this.props.logdate); 
    console.log('deleteSelectedRecord after'); 
    console.log('result ==> '+ result); 
    if (result) 
    { 
     this.setState({ showmodal: false }); 
     this.props.incrementCount(); 
    } 
    return result; 

    } 

    setModalVisible = (visible) => { 
    this.setState({showmodal: visible}); 
    } 

    onWeightClick =() => { 
     this.setState({ selecteddate: this.props.logdate, showmodal: true },() => { 

     console.log('Value in props==>' + this.props.logdate); 
     console.log('The selecteddate in the state ==> ' + this.state.selecteddate); 
     }); 

    } 

    onDateChange(date) { 
     this.setState({ 
      date: date 
     }); 
     } 

render() { 

    return (

    <View style={styles.containerStyle}> 
    <Modal 
      animationType="slide" 
      transparent={false} 
      visible={this.state.showmodal} 
      onRequestClose={() => {alert("Modal has been closed.")}} 
      > 
     <View style={{marginTop: 22}}> 
       <DatePickerIOS 
        date={this.state.date} 
        mode="date" 
        onDateChange={(date) => this.onDateChange(date)} 
        style={{ height: 100, width: 300 }} 
       /> 
     </View> 
     <View style={{ marginTop: 22, borderColor: '#ddd', borderWidth: 5 }}> 
       <TextInput 
        returnKeyType="done" 
        keyboardType='numeric' 
        style={{ 
        height: 40, 
        width: 60, 
        borderColor: 'gray', 
        borderWidth: 1, 

        }} 
        onChangeText={(text) => this.setState({ selectedweight: text })} 
        value={this.state.selectedweight.toString()} 
       /> 
       <Text>KG</Text> 
       <Button 
        title="Delete" 
        onPress={this.deleteSelectedRecord.bind(this)} 
        style={{ marginTop: 200 }} 
       /> 

     </View> 

     </Modal> 
       <View style={styles.headerContentStyle}> 
        <Text>{this.props.logstringdate}</Text> 
        <Text>{this.props.bmi}</Text> 
       </View> 
       <View style={styles.thumbnailContainerStyle}> 
        <Text onPress={this.onWeightClick}>{this.props.weight}</Text> 
       </View> 
    </View> 
); 

} 
}; 

const styles = { 
    containerStyle: { 
    borderWidth: 1, 
    borderRadius: 2, 
    borderColor: '#ddd', 
    borderBottomWidth: 0, 
    shadowColor: '#000', 
    shadowOffset: { width: 0, height: 2}, 
    shadowOpacity: 0.1, 
    shadowRadius: 2, 
    elevation: 1, 
    marginLeft: 5, 
    marginRight: 5, 
    marginTop:10, 
    }, 
    thumbnailContainerStyle: { 
    justifyContent: 'center', 
    alignItems: 'center', 
    marginLeft: 10, 
    marginRight: 10, 
    flexDirection: 'row' 

    }, 
    headerContentStyle: { 
    flexDirection: 'column', 
    justifyContent: 'space-around' 
    }, 
}; 

Antwort

2

Verschieben deleteSelectedRecord zum übergeordneten und aktualisieren seinen Zustand setState({ allLogs: [...] }) drin.

Indem Sie dies tun, lösen Sie das Elternelement aus, um es erneut zu rendern, und die Liste sollte erneut aktualisiert werden.

Die dümmste Logitem ist, desto besser. Denken Sie daran, wie würden Sie schreiben Test dafür gefälschte diese Aktion zum Löschen zum Beispiel.

1

Sie versuchen, count in der übergeordneten Komponente zu erhöhen, aber this.state.allLogs nicht ändern, was die Liste füttert. Wenn Sie incrementCounter aufrufen, übergeben Sie möglicherweise das Element, das gelöscht wird, nach oben, damit Sie es aus dem Array entfernen können, das die Liste füttert.

Die einzige negative Seite ist, dass Sie möglicherweise ein Array auf Ihren Händen haben, das nicht den tatsächlichen Status des Arrays in der DB darstellt.(Dateninkonsistenz)

So, dann könnten Sie Folgendes tun: Löschen Sie den Eintrag aus der DB aus der untergeordneten Komponente und rufen dann this.props.notifiyParent (umbenannt incrementCounter) und in der Mutter wo notifyParent definiert ist der Wert für this.state.allLogs abrufen und aktualisiere den Zustand des Elternteils -> dies wird ein erneutes Rendern auslösen und deine Elternkomponente wird nun die aktualisierte Liste anzeigen.

Auch, wie @mersocarlin suggeriert, ist es besser für die Kindkomponente, "dumm" zu sein, da sie nicht die Logik tragen muss, wie das Element gelöscht wird. Es muss nur die delete-Methode aufgerufen werden, die das übergeordnete Element weitergeben würde, und die delete-Methode würde im übergeordneten Element definiert. Außerdem werden auf diese Weise alle DB-Transaktionen von einem einzigen Ort (dem übergeordneten)

ausgeführt
Verwandte Themen