2017-07-21 5 views
1

Ich führe den folgenden Code in Android-Emulator, aber ich bekomme null ist kein Objekt (Bewertung 'this.state.dataSource') Fehler . Bitte, könnten Sie mir helfen zu sehen, was ich falsch mache? Aus irgendeinem Grund wird die Zeile dataSource={this.state.dataSource} auf Null gesetzt.ReactNative null ist kein Objekt (Bewertung 'this.state.dataSource')

import React, { 
    Component 
} from 'react'; 
import { 
    AppRegistry, 
    ActivityIndicator, 
    ListView, 
    Text, 
    View, 
    StyleSheet 
} from 'react-native'; 
import Row from './Row'; 
import Header from './Header'; 
import SectionHeader from './SectionHeader'; 

const styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    marginTop: 20, 
    }, 
    separator: { 
    flex: 1, 
    height: StyleSheet.hairlineWidth, 
    backgroundColor: '#8E8E8E', 
    }, 
}); 

export default class NoTocarList extends Component { 
    constructor(props) { 
    super(props); 
    const getSectionData = (dataBlob, sectionId) => dataBlob[sectionId]; 
    const getRowData = (dataBlob, sectionId, rowId) => 
     dataBlob[`${rowId}`]; 

    fetch('http://xxxxx.mybluemix.net/get') 
     .then((response) => response.json()) 
     .then((responseJson) => { 
     const ds = new ListView.DataSource({ 
      rowHasChanged: (r1, r2) => r1 !== r2, 
      sectionHeaderHasChanged: (s1, s2) => s1 !== s2, 
      getSectionData, 
      getRowData 
     }); 

     const { 
      dataBlob, 
      sectionIds, 
      rowIds 
     } = 
     this.formatData(responseJson); 

     this.state = { 
      dataSource: ds.cloneWithRowsAndSections(dataBlob, sectionIds, 
      rowIds) 
     } 
     }) 
    } 


    formatData(data) { 
    const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); 
    const dataBlob = {}; 
    const sectionIds = []; 
    const rowIds = []; 

    for (let sectionId = 0; sectionId < alphabet.length; sectionId++) { 
     const currentChar = alphabet[sectionId]; 
     const users = data.filter((user) => 
     user.calle.toUpperCase().indexOf(currentChar) === 0); 

     if (users.length > 0) { 
     sectionIds.push(sectionId); 

     dataBlob[sectionId] = { 
      character: currentChar 
     }; 
     rowIds.push([]); 

     for (let i = 0; i < users.length; i++) { 
      const rowId = `${sectionId}:${i}`; 
      rowIds[rowIds.length - 1].push(rowId); 
      dataBlob[rowId] = users[i]; 
     } 
     } 
    } 
    return { 
     dataBlob, 
     sectionIds, 
     rowIds 
    }; 
    } 

    render() { 
    return (
     <View style={{flex: 1, paddingTop: 20}}> 
     <ListView 
      style={styles.container} 
      dataSource={this.state.dataSource} 
      renderRow={(rowData) => <Row {...rowData} />} 
      renderSeparator={(sectionId, rowId) => <View key={rowId} />} 
      style={styles.separator} 
      renderHeader={() => <Header />} 
      renderSectionHeader={(sectionData) => <SectionHeader {...sectionData} />} 
     /> 
     </View> 
    ); 

    } 

} 


AppRegistry.registerComponent('NoTocar',() => NoTocarList); 

Error Message

Antwort

1

Das Problem ist, dass Sie den Zustand asynchron zu aktualisieren sind versucht, nach einem machen, aber das Ergebnis auf den ersten Render erwarten. Ein weiteres Problem ist, dass Sie den Status überschreiben, anstatt ihn zu aktualisieren.

Der Aufruf in Ihrem Konstruktor fetch ist asynchron, was bedeutet, dass der Konstruktor beendet ist und die Komponente (zusammen mit ihrem Status) erstellt wird, bevor der Aufruf verrechnet wird.

constructor() { 

    fetch('http://xxxxx.mybluemix.net/get') 
    // ... 
    .then(() => { 
    // ... 

    // this code gets called after the component is created 
    // this state is also overwriting already created state 
    this.state = { 
     dataSource: ds.cloneWithRowsAndSections(dataBlob, sectionIds, 
        rowIds) 
    } 
    }) 
} 

Da Ihre Daten asynchron erhalten wird, können Sie einen Scheck hinzufügen und eine Fortschrittsanzeige zeigen, während seine Belastung (auch setState statt Überschreiben des Staates verwendet werden soll):

constructor() { 

    this.state = { 
    dataSource: null // initialize it explicitly 
    } 

    fetch('http://xxxxx.mybluemix.net/get') 
    // ... 
    .then(() => { 
    // ... 

    // use set state 
    this.setState({ 
     dataSource: ds.cloneWithRowsAndSections(dataBlob, sectionIds, 
        rowIds) 
    }) 
    }) 
} 

render(){ 

    // on initial render, while the state hasn't been fetched yet 
    // show the spinner 
    if (!this.state.dataSource) { 
    return <ActivityIndicator /> 
    } 

    return(
    <View style={{flex: 1, paddingTop: 20}}> 
     ... 
    </View> 
); 
} 
+0

Vielen Dank für die Antworten einstellen müssen. Ich habe den Code aktualisiert und jetzt bekomme ich diesen Fehler ** null ist kein Objekt (Bewertung 'dataSource.rowIdentities') ** :( –

1

Von Ihrem Beispiel Sie haben die dataSource als null an die ListView übergeben. So müssen Sie es initialisieren zuerst von

mit
this.state({ 
    dataSource: {} 
}) 

Nach Erhalt der Antwort vom Api Anruf Sie die dataSource state unter Verwendung

this.setState({ 
    dataSource: ds.cloneWithRowsAndSections(dataBlob, sectionIds, 
        rowIds) 
}) 
Verwandte Themen