Search code examples
react-nativereact-native-sectionlist

Cannot read property 'length' of undefined when using SectionList


I call an api to get my movieData API: https://obscure-reaches-65656.herokuapp.com/api/getCloseTime?city=Hsinchu&sTime=18&eTime=21

I think the data is correct for SectionList, the data is an array with lots of object, but i still get the error:

Cannot read property 'length' of undefined

Can't figure it out how to fix the data problem ?

Here is console.log(movieData);:

enter image description here

Here is about my class component render:

render() {
    const movieData = this.props.searchTime;

    if (this.props.loading) {
      return <Spinner text='Loading...' />;
    }
    console.log('movieData =>');
    console.log(movieData);

    return (
      <View>
        <SectionList
          renderSectionHeader={this.sectionComp}
          renderItem={this.renderSectionItem}
          sections={movieData}
          ItemSeparatorComponent={() => <View><Text></Text></View>}
          ListHeaderComponent={() => <View style={{ backgroundColor: '#25B960', alignItems: 'center', height: 30 }}><Text style={{ fontSize: 18, color: '#ffffff' }}>Header</Text></View>}
          ListFooterComponent={() => <View style={{ backgroundColor: '#25B960', alignItems: 'center', height: 30 }}><Text style={{ fontSize: 18, color: '#ffffff' }}>Footer</Text></View>}
        />
      </View>
    );
  }
}

If i set a test data testSections instead of movieData its working.

const testSections = [
  { key: "A", data: [{ title: "test1-1" }, { title: "test1-2" }, { title: "test1-3" }] },
  { key: "B", data: [{ title: "test2-1" }, { title: "test2-2" }, { title: "test2-3" }, { title: "test2-4" }, { title: "test2-5" }] },
  { key: "C", data: [{ title: "test3-2" }, { title: "test3-2" }] },
  { key: "W", data: [{ title: "test4-1" }, { title: "test4-2" }, { title: "test4-3" },{ title: "test4-4" }, { title: "test4-5" }, { title: "4-6" }] },
];

My custom render function like this:

  renderSectionItem = (info) => {
    console.log('what is _renderItem info =>');
    console.log(info);
    const txt = '  ' + info.item.theaterCn;
    return <Text
      style={{ height: 60, textAlignVertical: 'center', backgroundColor: "#ffffff", color: '#5C5C5C', fontSize: 15 }}>{txt}</Text>
  }

  sectionComp = (info) => {
    console.log('what is  _sectionComp info =>');
    console.log(info);
    const txt = info.section.key;
    return <Text
      style={{ height: 50, textAlign: 'center', textAlignVertical: 'center', backgroundColor: '#9CEBBC', color: 'white', fontSize: 30 }}>{txt}</Text>
  }

I don't know why.

Any help would be appreciated. Thanks in advance.


Solution

  • The data structure movieData is not correct, SectionList expect an array of objects where each object should have title and data property, take a look at the documentation here. So, as per your movieData, you need to transform the values into that structure, like

    Sample

    First, transform the fetched data into the proper structure

    fetch('https://obscure-reaches-65656.herokuapp.com/api/getCloseTime?city=Hsinchu&sTime=18&eTime=21')
    .then(r => r.json())
    .then(r => {
      const movieData = r.reduce((r,s) => {
        r.push({title: s.theater, data: s.movie});
        return r;
      }, []);
    
      this.setState({ movieData });
    });
    

    Once you have transformed the data, just pass it to SectionList

    <SectionList
          renderItem={({item, index, section}) => <Text key={index}>{item.enName}</Text>}
          renderSectionHeader={({section: {title}}) => (
            <Text style={{fontWeight: 'bold'}}>{title}</Text>
          )}
          sections={this.state.movieData}
          keyExtractor={(item, index) => item.enName + index}
    />
    

    Hope this will help!