React native expo - 从 FlatList 导航到详细信息屏幕

Posted

技术标签:

【中文标题】React native expo - 从 FlatList 导航到详细信息屏幕【英文标题】:React native expo - Navigate from FlatList to detail screen 【发布时间】:2020-05-07 18:03:01 【问题描述】:

这里是 React Native 菜鸟。我正在尝试根据我的学习需求调整 React Native expo 选项卡式应用程序。我目前正在处理 Flatlists,我想打开一个新屏幕,将 FlatList 的任何项目作为项目道具的参数发送。我已经达到了某个点,但似乎无法成功完成它。

HomeScreen.js

import * as WebBrowser from 'expo-web-browser';
import React from 'react';
import Image,Platform,ScrollView,StyleSheet,Text,TouchableOpacity,View, from 'react-native';
import  SafeAreaView  from 'react-native';
import SearchableFlatList from '../navigation/SearchableList';
import  MonoText  from '../components/StyledText';

export default function HomeScreen() 
    return (
        <SafeAreaView style= flex: 1, backgroundColor: '#fff' >
            <SearchableFlatList/>
        </SafeAreaView>
    );


class LogoTitle extends React.Component 
    render() 
        return (
            <React.Fragment>
                <Image
                    source=require('../assets/images/icon.png')
                    style= width: 30, height: 30 
                />
                <Text style= fontSize: 30 >
                    AgriPrices
                </Text>
            </React.Fragment>
        );
    


HomeScreen.navigationOptions = 
    headerTitle: () => <LogoTitle />,
    headerStyle: backgroundColor: '#f4511e',,
    headerTintColor: '#fff',
    headerTitleStyle: fontWeight: 'bold',,
;

MainTabNavigator.js

import React from 'react';
import  Platform  from 'react-native';
import  createStackNavigator  from 'react-navigation-stack';
import  createBottomTabNavigator  from 'react-navigation-tabs';
import TabBarIcon from '../components/TabBarIcon';
import HomeScreen from '../screens/HomeScreen';
import LinksScreen from '../screens/LinksScreen';
import SettingsScreen from '../screens/SettingsScreen';

const config = Platform.select(web:  headerMode: 'screen' ,default: ,);

const HomeStack = createStackNavigator(Home: HomeScreen,,config);
HomeStack.navigationOptions = 
  tabBarLabel: 'Home',
  tabBarIcon: ( focused ) => (<TabBarIcon focused=focused name=Platform.OS === 'ios' ? `ios-home$focused ? '' : '-outline'` : 'md-home'/>),
;
HomeStack.path = '';

const LinksStack = createStackNavigator(Links: LinksScreen,,config);
LinksStack.navigationOptions = 
  tabBarLabel: 'Info',
  tabBarIcon: ( focused ) => (<TabBarIcon focused=focused name=Platform.OS === 'ios' ? `ios-information-circle$focused ? '' : '-outline'` : 'md-information-circle'/>),
;
LinksStack.path = '';

const SettingsStack = createStackNavigator(Settings: SettingsScreen,,config);
SettingsStack.navigationOptions = 
  tabBarLabel: 'Settings',
  tabBarIcon: ( focused ) => (<TabBarIcon focused=focused name=Platform.OS === 'ios' ? 'ios-settings' : 'md-settings' />),
;
SettingsStack.path = '';

const tabNavigator = createBottomTabNavigator(HomeStack,SettingsStack,LinksStack,);
tabNavigator.path = '';

export default tabNavigator;

SearchableFlatlist.js

import React,  Component  from 'react';
import  View, Text, FlatList, ActivityIndicator, Alert  from 'react-native';
import  ListItem, SearchBar  from 'react-native-elements';
import DetailsScreen from '../screens/DetailsScreen';

class MyFlatList extends Component 
  constructor(props) 
    super(props);
    this.state = 
      loading: false,
      data: [],
      error: null,
    ;
    this.arrayholder = [];
  

  componentDidMount() 
    this.makeRemoteRequest();
  

  makeRemoteRequest = () => 
    const url = 'http://dummyurl.com';
    this.setState( loading: true );
    fetch(url)
      .then(res => res.json())
      .then(res => 
        this.setState(data: res,error: res.error || null,loading: false,);
        this.arrayholder = res;
      )
      .catch(error => 
        this.setState( error, loading: false );
      );
  ;

  renderSeparator = () => 
    return (
      <View
        style=
          height: 1,
          width: '86%',
          backgroundColor: '#CED0CE',
          marginLeft: '14%',
        
      />
    );
  ;

  searchFilterFunction = text => 
    this.setState(
      value: text,
    );
    const newData = this.arrayholder.filter(item => 
      const itemData = `$item.description.toUpperCase() $item.product.toUpperCase() $item.product.toUpperCase()`;
      const textData = text.toUpperCase();
      return itemData.indexOf(textData) > -1;
    );
    this.setState(
      data: newData,
    );
  ;

  _onPress(item) 
    this.props.navigation.navigate('Details', product: item.product,description: item.description,);
  

  renderHeader = () => 
    return (
      <SearchBar
        placeholder="Type Here..."
        lightTheme
        round
        onChangeText=text => this.searchFilterFunction(text)
        autoCorrect=false
        value=this.state.value
      />
    );
  ;

  render() 
    if (this.state.loading) 
      return (
        <View style= flex: 1, alignItems: 'center', justifyContent: 'center' >
          <ActivityIndicator />
        </View>
      );
    
    const myicons = [
      title: 'Cotton',file: require('../assets/images/cotton.png'),,
      title: 'Beef',file: require('../assets/images/beef.png'),,
      title: 'Bananas',file: require('../assets/images/banana.png'),,
      title: 'Butter',file: require('../assets/images/butter.png'),,
      title: 'Cocoa',file: require('../assets/images/cocoa.png'),,
      title: 'Coffee',file: require('../assets/images/coffee.png'),,
      title: 'Corn',file: require('../assets/images/corn.png'),,
      title: 'Cotton',file: require('../assets/images/cotton.png'),,
      title: 'Eggs',file: require('../assets/images/eggs.png'),,
      title: 'Meat',file: require('../assets/images/meat.png'),,
      title: 'Milk',file: require('../assets/images/milk.png'),,
      title: 'Oils',file: require('../assets/images/oil.png'),,
      title: 'Oranges',file: require('../assets/images/orange.png'),,
      title: 'Rice',file: require('../assets/images/rice.png'),,
      title: 'Shrimps',file: require('../assets/images/shrimp.png'),,
      title: 'Sugar',file: require('../assets/images/sugar.png'),,
      title: 'Tea',file: require('../assets/images/tea.png'),,
      title: 'Tobacco',file: require('../assets/images/tobacco.png'),,
      title: 'Wheat',file: require('../assets/images/wheat.png'),,
      title: 'Wool',file: require('../assets/images/wool.png'),,
      title: 'Oats',file: require('../assets/images/oat.png'),,
      title: 'Indexes',file: require('../assets/images/index.png'),,
    ];
    const  navigate  = this.props.navigation;
    return (
      <View style= flex: 1 >
        <FlatList
          data=this.state.data
          renderItem=( item ) => (
            <ListItem
              leftAvatar= source: myicons.filter(myitem => myitem.title === item.product)[0].file 
              title=item.description
              rightTitle=item.price.toString()
              subtitle=item.date
              onPress=() => navigate('Details',  product: item.product )
            />
          )
          keyExtractor=item => item.description
          ItemSeparatorComponent=this.renderSeparator
          ListHeaderComponent=this.renderHeader
        />
      </View>
    );
  


export default MyFlatList;

DetailsS​​creen.js

import React from 'react';
import Text, Image,ScrollView, StyleSheet  from 'react-native';

export default function DetailsScreen() 
  var product =this.props.navigation.getParam('product', 'No Name'); //second parameter is a callback
  return (
    <View style= flex: 1, alignItems: 'center', justifyContent: 'center' >
      <Text>The product is this.props.navigation.state.params.product||'NoName' /*NoName is also a callback*/</Text>
    </View>
  );


DetailsScreen.navigationOptions = 
  headerTitle: () => <LogoTitle />,
    headerStyle: 
      backgroundColor: '#f4511e',
    ,
    headerTintColor: '#fff',
    headerTitleStyle: 
      fontWeight: 'bold',
    ,
;

class LogoTitle extends React.Component 
  render() 
    return (
      <React.Fragment>
          <Image
            source=require('../assets/images/icon.png')
            style= width: 30, height: 30 
          />
          <Text style= fontSize: 30 >
            AgriPrices
        </Text>
      </React.Fragment>
    );
  


const styles = StyleSheet.create(
  container: 
    flex: 1,
    paddingTop: 15,
    backgroundColor: '#fff',
  ,
);

当我按下 HomeScreen 的 SearchableFlatList 的一项时,我需要打开 DetailsS​​creen,方法是将 description 作为参数传递。使用上面的代码,我得到一个错误 undefined is not an object (evalating 'this.props.navigation.navigate')。我怎样才能超越这个?

【问题讨论】:

【参考方案1】:

我建议您使用堆栈导航器包装 MyFlatList 和 DetailsS​​creen。

const finalStack = createStackNavigator(

    MyFlatList: MyFlatList,
    DetailsScreen: DetailsScreen
,

    headerMode: 'none'
);

完成此操作后,'this.props.navigation.navigate' 将不会未定义。 截至目前,这两个屏幕之间没有导航链接。

问:为什么我选择堆栈导航器? A:因为你不希望 FlatList 在屏幕切换上重复渲染。

【讨论】:

你指的是哪个文件?顺便说一句,感谢您的时间。 在 HomeScreen.js 中,将 SearchableFlatList 替换为我建议的堆栈导航器。如果您遇到任何问题,请告诉我。 如果我按照你的建议添加代码,它首先会给出一个未知变量 MyFlatList 的错误。因此,我在您的代码中将 FlatList 更改为 SearchableFlatList,就像在导入中一样。现在,它为 this.props.navigation.navigate 给出了相同的未定义错误。 我只是大致了解了它的工作原理,您不应该复制该代码。请在snack.expo.io 上进行工作演示。我帮你会更容易。 MyFlatList 应该是 HomeScreen.js 中的 SearchableFlatList

以上是关于React native expo - 从 FlatList 导航到详细信息屏幕的主要内容,如果未能解决你的问题,请参考以下文章

从 Expo.MapView React-native 将 fitToSuppiedMarkers 应用到我的地图的正确方法是啥?

如何从 React Native Expo 推送通知中取消订阅(删除监听器)

React Native Expo 音频 |从最新位置播放直播

React native expo - 从 FlatList 导航到详细信息屏幕

Expo - 网络响应超时错误 (create-react-native-app) (Windows 10)

从使用 Expo SDK 构建的 React-Native 应用程序将照片分享到 Instagram