在无状态组件中使用 Flatlist 响应本机导航

React native navigation with a Flatlist in a stateless component

我正在尝试创建无状态组件来显示平面列表,但我在导航方面遇到了困难。

这是我的 'main' app.js,精简后的:

import React from 'react';
import { AppRegistry, FlatList, ActivityIndicator, Text, View, Image, StyleSheet } from 'react-native';
import { StackNavigator } from 'react-navigation'
import Strip from '../components/Strip'

export default class FetchData extends React.Component {

    constructor(props){
        super(props);
        this.state ={ isLoading: true}
    }

    componentDidMount(){
        ...
    }


    render(){
        if(this.state.isLoading){
            ...
        }
        return (
            <View>
                <Strip props={this.state.dataSource.strips} />
            </View>
        )
    }
}

这是组件:

import React from 'react';
import { FlatList, Text, View, Image, StyleSheet, TouchableOpacity } from 'react-native';

renderItem = ({item}) => (
    <TouchableOpacity onPress={() => this.props.navigation.navigate('Details')} >
        <View style={{width: 136}}>
            ...
            <Text>some text</Text>
        </View>
    </TouchableOpacity>
);

const Strip = (props) => {
    return Object.keys(props).map(function(key, i) {
        return Object.keys(props[key]).map((strips, i) => {
            var strip = props[key][strips];
            return(
                <View>
                    <Text>{strip.title}</Text>
                    <FlatList horizontal
                        data={strip.someobjects}
                        renderItem={({item}) => this.renderItem(item)}
                    />     
                </View>
            )
        });
    })
}

export default Strip;

列表已显示,但当然,当我触摸某个项目时,出现“未定义不是对象(正在评估“_this.props.navigation”)”错误。

我知道我不能在无状态组件上使用 this.props.navigation.navigate,但我只是不明白如何通过无状态组件中的平面列表传递导航道具。

它必须非常简单,比如使用 navigate('Details') 并放置 const { navigate } = this.props.navigation; 某处。但是在哪里呢?

在 parent 中定义一个导航函数,并通过 props 将其传递给 child。

例如:

Parent


parentNavigate(destination){
 this.props.navigation.navigate(destination);
}

render(){
        if(this.state.isLoading){
            ...
        }
        return (
            <View>
                <Strip props={this.state.dataSource.strips} parentNavigate={(destination) => this.parentNavigate(destination)}/>
            </View>
        )
    }

Child


renderItem = (item, parentNavigate) => (
    <TouchableOpacity onPress={parentNavigate('Details')} >
        <View style={{width: 136}}>
            ...
            <Text>some text</Text>
        </View>
    </TouchableOpacity>
);

const Strip = (props, parentNavigate) => {
    return Object.keys(props).map(function(key, i) {
        return Object.keys(props[key]).map((strips, i) => {
            var strip = props[key][strips];
            return(
                <View>
                    <Text>{strip.title}</Text>
                    <FlatList horizontal
                        data={strip.someobjects}
                        renderItem={(item, parentNavigate) => this.renderItem(item, parentNavigate)}
                    />     
                </View>
            )
        });
    })
}

而不是 Strip 组件中的 navigate,为 Strip 提供一个 onPress 处理程序并从那里导航。如果 FetchDataStackNavigator 的一部分,那么您可以轻松地从该组件 navigate

考虑以下示例

...
export default class FetchData extends React.Component {
 ...
 handleOnPress = () => {
  this.props.navigation.navigate('Details')
 }

 render() {
  if(this.state.isLoading){
   ...
  }
  return (
   <View>
    <Strip 
     props={this.state.dataSource.strips} 
     onPress={this.handleOnPress} 
    />
   </View>
  );
 }
}

Strip组件中,可以绑定onPress处理程序

 const Strip = (props) => {
  renderItem = ({item}) => (
   <TouchableOpacity onPress={props.onPress} >
    <View style={{width: 136}}>
     ...
    <Text>some text</Text>
   </View>
  </TouchableOpacity>
 );

 return Object.keys(props).map(function(key, i) {
  return Object.keys(props[key]).map((strips, i) => {
   var strip = props[key][strips];
    return(
     <View>
      <Text>{strip.title}</Text>
       <FlatList horizontal
         data={strip.someobjects}
         renderItem={({item}) => renderItem(item)}
       />     
      </View>
     )
  });
})
}

希望这会有所帮助!