Salman
Salman

Reputation: 1034

Searching through ListView

I've read through the react native docs and through react native express.

I'm trying to learn react native trough experience and building apps.

My current issue happens after I created an static ListView and try to filter through it. I've found an example of how another was able to achieve it, but I get the error:

undefined is not an object (evaluating 'this.state.rows.length')

I though rows was defined in:

    state = {
    dataSource: ds.cloneWithRows(rows)
  }

So I'm confused to where the error comes from.

app file

import React, { Component } from 'react';

import { 
    AppRegistry,
    ListView, 
    View, 
    Text, 
    StyleSheet, 
    Image, 
    Button, 
    TouchableOpacity, 
    TextInput, 
    ScrollView,
    Icon,
} from 'react-native';

import { createStackNavigator, } from 'react-navigation';

const image1 = require('./assets/card-0.png')
const image2 = require('./assets/card-2.png')
const image3 = require('./assets/card-3.png')
const image4 = require('./assets/card-4.png')
const image5 = require('./assets/card-5.png')

// Row data (hard-coded)
const rows = [
  {id: 0, club: 'Club Air', genre: 'Hip Hop / R&B', image: image1},
  {id: 1, club: 'Abe', genre: 'Hip Hop / R&B', image: image2},
  {id: 2, club: 'John Doe', genre: 'Hip Hop / R&B', image: image3},
  {id: 3, club: 'Encore', genre: 'Hip Hop / R&B', image: image4},
  {id: 4, club: 'Jimmy Whoo', genre: 'Hip Hop / R&B', image: image5},
]

// Row comparison function
const rowHasChanged = (r1, r2) => r1.id !== r2.id

// DataSource template object
const ds = new ListView.DataSource({rowHasChanged})

export class HomeScreen extends Component {
    static navigationOptions = {
        // title: ' Alpha',
        header: null,
    };

  state = {
    dataSource: ds.cloneWithRows(rows)
  }

  setSearchText(event){
    const searchText = event.nativeEvent.text;

    clubsLength = this.state.rows.length;
    aClub= this.state.rows;

    const filteredClubs = this.state.rows.filter(checkTitle);
    console.log("clubs: " + JSON.stringify(filteredClubs));

    function checkClub() {
        for(i=0;i<clubsLength;i++){
          if(aClub[i].club === searchText){
            console.log("found:  " + aClub[i].club);
            return aClub[i];
          }
        }
    }

    this.setState({
        searchText,
        dataSource: this.state.dataSource.cloneWithRows(filteredClubs),
    });
  }

  renderRow = (rowData) => { 
    return (

        <View style={styles.card}>
            <TouchableOpacity onPress={() => this.props.navigation.navigate('Details')}> 
                <View style={styles.innerCard}>
                    <Image 
                        style={styles.imageCard} 
                        source={rowData.image}
                    />
                    <Text style={styles.innerText}>
                        {rowData.club}
                    </Text>
                </View>
                <View style={styles.outerCard}>
                    <Text style={styles.outerText}>
                        {rowData.genre}
                    </Text>
                    <Text style = {styles.outerTexts}>
                       View
                    </Text>
                </View>
            </TouchableOpacity>
        </View>
    )
  }


  render() {
    return (

        <ScrollView style={styles.container}>
            <View style={styles.SearchBarContainer}>
                <TextInput  
                placeholder="Search"
                value={this.state.searchText}
                onChange={this.setSearchText.bind(this)}
                style={styles.searchBar}
                underlineColorAndroid="#DD016B"
                selectionColor="#DD016B"
                />
            </View>
            <ListView
            style={styles.listContainer}
            dataSource={this.state.dataSource}
            renderRow={this.renderRow}
            />
        </ScrollView>

    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'black',
    width:'100%',
    // height: 299,

  },
  SearchBarContainer: {
    justifyContent: 'center',
    alignItems: 'center'
  },
  listContainer: {
    flex: 1,
    backgroundColor: 'black',
    width:'100%',
    // height: 299,
  },
  button: {
    backgroundColor: 'transparent',
    width: '50%',
  },
  textInput: {
    height: 30,
    borderWidth: 1,
    borderColor: '#DD016B',
    marginBottom: 10,
    marginHorizontal: 10,
  },
  searchBar: {
    textAlign: 'center',
    height: 40, 
    width:200,
    color: '#DD016B',
    borderColor: '#DD016B', 
    // selectionColor: '#DD016B',
    // borderWidth: 1,
    // borderRadius: 5,
    marginBottom:20,
    marginTop: 20,
    justifyContent: 'center',
  },
  card: {
    marginBottom: 15,
  },
  innerCard: {
    height:110,
  },
  imageCard: {
    width: 500,
    height: 150,
    paddingTop: 0,
    paddingBottom: 0, 
    marginBottom:0, 
    marginTop: 0,
  },
  innerText: {
    color: 'white',
    marginBottom: 0,
    fontSize: 35,
    position: 'absolute',
    top: 100,
  },
  outerText: {
    color: '#DD016B',
    marginBottom: 0,
    marginTop: 50,
    width: 100,
  },
})

AppRegistry.registerComponent('App', () => App)

export default createStackNavigator({
  Home: {
    screen: HomeScreen,
  },
}, {
    initialRouteName: 'Home',
});

Upvotes: 1

Views: 224

Answers (1)

Tholle
Tholle

Reputation: 112917

The reason why you get your error is because you are trying to read rows from your state, but rows is an array outside of your component.

You could either reference the rows array that is outside of your state, or put the array in state when you create it.

Example

export class HomeScreen extends Component {
  static navigationOptions = {
    header: null
  };

  state = {
    dataSource: ds.cloneWithRows(rows),
    rows
  };

  // ...
}

Upvotes: 1

Related Questions