反应本地博览会-从FlatList导航到详细信息屏幕

时间:2020-01-21 16:14:21

标签: react-native expo screen react-native-flatlist react-native-navigation

在此处与本机新秀互动。我正在尝试根据我的学习需求调整React Native博览会选项卡式应用程序。我目前正在使用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。通过上面的代码,我得到一个错误 undefined不是一个对象(评估'this.props.navigation.navigate')。我该如何超越?

1 个答案:

答案 0 :(得分:1)

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

const finalStack = createStackNavigator(
{
    MyFlatList: MyFlatList,
    DetailsScreen: DetailsScreen
},
{
    headerMode: 'none'
});

完成此操作后,'this.props.navigation.navigate'将不再是未定义的。 到目前为止,这两个屏幕之间没有导航链接。

问:为什么选择堆栈导航器? 答:因为您不希望FlatList在屏幕开关上重复呈现。