具有导航的React-native ListView

时间:2017-11-12 01:34:06

标签: javascript listview react-native navigation

我正在尝试使用组件ListView和导航,但我得到undefined不是一个对象(评估'_this.props.navigator')错误

我的ListView位于Contacts.js

import React, { Component } from 'react';
import { AppRegistry, StyleSheet, ListView, Text, View, Navigator  } from 'react-native';
import Row from './Row'
import SearchBar from './SearchBar'
import Sections from './Sections'
import Load from './Load'
import demoData from './data'
import Pagination from '../Pagination';

export default class Contacts extends React.Component{
    constructor(props) {
        super(props)

        const getSectionData = (dataBlob, sectionId) => dataBlob[sectionId];
        const getRowData = (dataBlob, sectionId, rowId) => dataBlob[`${rowId}`];

        const ds = new ListView.DataSource({
          rowHasChanged: (r1, r2) => r1 !== r2,
          sectionHeaderHasChanged : (s1, s2) => s1 !== s2,
          getSectionData,
          getRowData,
        });

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

        // Init state
        this.state = {
            dataSource: ds.cloneWithRowsAndSections(dataBlob, sectionIds, rowIds),
            left: true,
            center: false,
            right: false
        }
    }

formatData(data) {
    // We're sorting by alphabetically so we need the alphabet
    const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');

    // Need somewhere to store our data
    const dataBlob = {};
    const sectionIds = [];
    const rowIds = [];

    // Each section is going to represent a letter in the alphabet so we loop over the alphabet
    for (let sectionId = 0; sectionId < alphabet.length; sectionId++) {
        // Get the character we're currently looking for
        const currentChar = alphabet[sectionId];

        // Get users whose first name starts with the current letter
        const users = data.filter((user) => user.name.first.toUpperCase().indexOf(currentChar) === 0);

        // If there are any users who have a first name starting with the current letter then we'll
        // add a new section otherwise we just skip over it
        if (users.length > 0) {
            // Add a section id to our array so the listview knows that we've got a new section
            sectionIds.push(sectionId);

            // Store any data we would want to display in the section header. In our case we want to show
            // the current character
            dataBlob[sectionId] = { character: currentChar };

            // Setup a new array that we can store the row ids for this section
            rowIds.push([]);

            // Loop over the valid users for this section
            for (let i = 0; i < users.length; i++) {
                // Create a unique row id for the data blob that the listview can use for reference
                const rowId = `${sectionId}:${i}`;

                // Push the row id to the row ids array. This is what listview will reference to pull
                // data from our data blob
                rowIds[rowIds.length - 1].push(rowId);

                // Store the data we care about for this row
                dataBlob[rowId] = users[i];
            }
        }
    }

    return { dataBlob, sectionIds, rowIds };
    }

    render() {
        return (
            <View style={styles.contactsContainer} >
                <Pagination 
                    left={this.state.left}
                    center={this.state.center}
                    right={this.state.right}
                />
                <ListView
                style={styles.listContainer}
                dataSource={this.state.dataSource}
                renderRow={(data) => <Row {...data} navigator={this.props.Navigator} />}
                renderSeparator={(sectionId, rowId) => <View key={rowId} style={styles.separator} />}
                renderHeader={() => <SearchBar />}
                renderFooter={() => <Load />}
                renderSectionHeader={(sectionData) => <Sections {...sectionData} />}
                />
            </View>
        );
    }
}

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

renderRow = {(data)=&gt; }

调用Row.js并打印联系人数据

import React from 'react';
import ProfileScreen from './ProfileScreen'
import { AppRegistry, View, Text, StyleSheet, TouchableHighlight, Alert, Navigator } from 'react-native';

const Row = (props) => (
    <TouchableHighlight onPress={() => this.props.Navigator.push({ screen: 'ProfileScreen' })} underlayColor="#FFFFFF">
        <View style={ styles.container }>
            <View style={ styles.status } />
            <Text style={ styles.text }>
                {`${ props.name.first } ${ props.name.last }`}
            </Text>
        </View>
    </TouchableHighlight>
);

const styles = StyleSheet.create({
    container: {
        flex: 1,
        padding: 12,
        flexDirection: 'row',
        alignItems: 'center',
    },
    text: {
        marginLeft: 12,
        fontSize: 16,
    },
    status: {
        backgroundColor: '#5cb85c',
        height: 10,
        width: 10,
        borderRadius: 20,
    },
});

export default Row;

正如您所看到的那样,每行都有一个TouchableHighlight,它应该导航到ProfileScreen

修改

请勿使用导航员擅自使用STACKNAVIGATOR

1 个答案:

答案 0 :(得分:2)

导入Navigator模块时无需使用this.props.Navigator。只需使用Navigator。 this.props包含您传递给组件的所有属性的列表

例如:

<强> Parent.js

class Parent extends React.Component {
  render() {
    <Child firstProp={"FirstProp"} secondProps={"SecondProp"} />
  }
}    

<强> Child.js

import {externalImport} from './externalFile'

class Child extends React.Component{
  render() {
    <div>
       I AM FIRST PROP {this.props.firstProp}
       I AM SECOND PROP {this.props.secondProp}
       I AM NOT A PROP, JUST AN IMPORT { externalImport }
    </div>
  }
}