带有导航的 React-native ListView

Posted

技术标签:

【中文标题】带有导航的 React-native ListView【英文标题】:React-native ListView with Navigation 【发布时间】:2018-04-24 23:17:53 【问题描述】:

我正在尝试将组件 ListView 与 Navigation 一起使用,但我得到 undefined is not an object (evalating'_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=(数据) =>

调用 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

编辑

不要使用 NAVIGATOR,它已被弃用 INSTED USE STACKNAVIGATOR

【问题讨论】:

请贴出定义navigator的父组件。 我在每个文件上都定义了导航器。我发布了整个文件,以便您查看。 以下答案是否解决了问题? 【参考方案1】:

在导入 Navigator 模块时无需使用 this.props.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>
  

【讨论】:

你说得对,但我发现 Navigator 已经贬值了。

以上是关于带有导航的 React-native ListView的主要内容,如果未能解决你的问题,请参考以下文章

React-Native:无法导航到第二个屏幕

React Native刷新屏幕/组件/更改状态

是否可能带有子页面的反应导航抽屉?

React-Native:导航到堆栈导航器中的抽屉

React-native 导航实验示例?

react-native:无法读取未定义的属性“导航”