首页 > 解决方案 > 在 react-native 的两个页面之间传输数据之前需要它

问题描述

我想在我的应用程序的两个页面之间传输数据,通常我的语法没有任何问题,this.props.navigation.state.params...但在这种情况下,问题是 itemCategory 是未定义的,因为我的第一页(初始路由)是HomeScreen,而我的第二页是CategoryListScreen. 那么究竟发生了什么:

  1. 用户启动应用程序并登陆主屏幕
  2. 在构造函数中,我正在尝试使用暂时未定义的 itemCategory 修改状态类别

    this.state = { 类别:this.props.navigation.state.params.itemCategory, restaurantData: [], }

  3. 应用程序崩溃,因为 this.props.navigation.state.params.itemCategory 未定义

我试图更改初始路由,CategoryListScreen并且数据已正确设置在我的 HomeScreen 页面的状态类别中,因为它现在是我的第二页。

所以我想知道的是如何设置变量类别而不会使应用程序崩溃......

用户使用CategoryListScreen来选择他想吃的食物类型,因此我可以调用我的 API 以仅显示具有此类食物的餐厅。

/*Beginning CategoryListScreen*/

import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { FlatList, Image, Text, TouchableOpacity, View } from 'react-native'
import {environment} from '../../environments/environment'
import axios from '../../interceptor/tokenInterceptor'
import Hamburger from '../../components/Hamburger/Hamburger'
import styles from './styles'

const menuData = [
    { 
        id: '1',
        title: 'Burger',
        image: require('../../assets/images/burger.jpg'),
      },
      { 
        id: '2',
        title: 'Pizza',
        image: require('../../assets/images/pizza.jpeg'),
      },
      { 
        id: '3',
        title: 'Sushi',
        image: require('../../assets/images/sushi.jpg'),
      },
      { 
        id: '4',
        title: 'Tacos',
        image: require('../../assets/images/tacos.jpeg'),
      },
      { 
        id: '5',
        title: 'Chinois',
        image: require('../../assets/images/plat_chinois.jpg'),
      },
      { 
        id: '6',
        title: 'Français',
        image: require('../../assets/images/plat_français.jpg'),
      },
      { 
        id: '7',
        title: 'Mexicain',
        image: require('../../assets/images/mexicain.jpg'),
      },
      { 
        id: '8',
        title: 'Italien',
        image: require('../../assets/images/italien.jpg'),
      },
]

class CategoryListScreen extends Component {
  static navigationOptions = ({navigation}) => ({
    title: 'Menu',
    headerLeft: (
      <Hamburger
        onPress={() => {
          navigation.openDrawer()
        }}
      />
    ),
  })

  constructor(props) {
    super(props)

    this.state = {
      restaurantData: [],
    }
  }

  onPress = itemCategory => {
    // console.log('category : ', itemCategory);
    this.props.navigation.navigate('HomeScreen', {itemCategory})
    // console.log(item);
    // this.getRestaurantByCategories(item)
  }

  renderItem = ({item}) => (
    <TouchableOpacity onPress={() => this.onPress(item.title)}>
      <View style={styles.container}>
        <Image style={styles.photo} source={item.image}/>
        <View style={styles.overlay} />
        <Text numberOfLines={3} style={styles.title}>
          {item.title}
        </Text>
      </View>
    </TouchableOpacity>
  )

  render() {
    return (
      <FlatList
        vertical
        showsVerticalScrollIndicator={false}
        numColumns={2}
        data={menuData}
        renderItem={this.renderItem}
        keyExtractor={item => `${item.id}`}
      />
    )
  }
}

CategoryListScreen.propTypes = {
  navigation: PropTypes.shape({
    navigate: PropTypes.func.isRequired,
  }),
}

export default CategoryListScreen

/*End CategoryListScreen*/


/*Beginning HomeScreen*/

import PropTypes from 'prop-types'
import React from 'react'
import {
  AsyncStorage,
  FlatList,
  Image,
  ScrollView,
  Text,
  TouchableHighlight,
  View,
} from 'react-native'
import _ from 'lodash'
import Hamburger from '../../components/Hamburger/Hamburger'
import ShoppingCartButton from '../../components/ShoppingCartButton/ShoppingCartButton'
import {environment} from '../../environments/environment'
import axios from '../../interceptor/tokenInterceptor'
import styles from './styles'

const categoriesData = [
  {
    id: '1',
    title: 'Burger',
    image: require('../../assets/images/burger.jpg'),
  },
  {
    id: '2',
    title: 'Pizza',
    image: require('../../assets/images/pizza.jpeg'),
  },
  {
    id: '3',
    title: 'Sushi',
    image: require('../../assets/images/sushi.jpg'),
  },
  {
    id: '4',
    title: 'Tacos',
    image: require('../../assets/images/tacos.jpeg'),
  },
  {
    id: '5',
    title: 'Chinois',
    image: require('../../assets/images/plat_chinois.jpg'),
  },
  {
    id: '6',
    title: 'Cuisine',
    image: require('../../assets/images/plat_français.jpg'),
  },
]

/**
 * Construit le component catégorie en haut de la page
 */
ItemCategory = ({title, image}) => {
  return (
    <View>
      <Image source={image} style={styles.categoryItemPhoto} />
      <Text style={styles.categoryItemTitle}>{title}</Text>
    </View>
  )
}

/**
 * Construit les composant restaurant
 */
ItemRestaurant = ({id, title, image, distance, categories}) => {
  return (
    <View>
      {/* <Text>{id}</Text> */}
      {/* <Image source={{uri: `data:image/png;base64,${image}`}}  style={styles.foodPhoto}/> */}
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.textRestaurant}>
        distance depuis votre position : {distance}m
      </Text>
      <Text style={styles.textRestaurant}>Catégories : {`${categories}`}</Text>
    </View>
  )
}

export default class HomeScreen extends React.Component {
  static navigationOptions = ({navigation}) => ({
    title: 'Home',
    headerLeft: () => (
      <Hamburger
        onPress={() => {
          navigation.openDrawer()
        }}
      />
    ),
    headerRight: () => (
      <ShoppingCartButton
        onPress={() => {
          navigation.navigate('CartScreen')
        }}
      />
    ),
  })

  constructor(props) {
    super(props)
    // if (this.props.navigation.state.params.itemCategory === undefined) {
    //   console.log('dans le if')
    //   this.state = {
    //     restaurantData: [],
    //   }
    // } else {
    //   this.state = {
    //     categories: this.props.navigation.state.params.itemCategory,
    //     restaurantData: [],
    //   }
    // }
    // if (this.props.navigation.state.params.itemCategory === undefined) {
    //   console.log('je suis undefined');
    // }
    this.state = {
          // categories: this.props.navigation.state.params.itemCategory,
          categories: this.props.navigation.getParam('itemCategory', 'NO_VALUE'),
          // categories: _.get(this.props, 'navigation.state.params.itemCategory'),
          restaurantData: [],
        }
  }

  componentDidMount() {
    console.log('dans le componentdidmount : ', this.state.categories);
    this.getRestaurant()
  }

  /**
   * Récupère la liste de tous les restaurants à moins de 30km du user
   */
  getRestaurant = async () => {
    try {
      let res = await axios({
        method: 'get',
        url: `${environment.apiDevUrl}/restaurant/visible`,
      })
      this.setState({
        restaurantData: res.data,
      })
    } catch (error) {
      console.error(error)
    }
  }

  getCategories = async () => {
    try {
      let res = await axios({
        method: 'get',
        url: `${environment.apiDevUrl}/restaurant/category/Pizza`,
      })
    } catch (error) {
      console.error(error)
    }
  }

  /**
   * Affiche seulement les restaurants en fonction de la catégorie choisi par le user
   */
  getRestaurantByCategories = async (item) => {
    console.log('item : ',item);
    try {
      let res = await axios({
        method: 'post',
        url: `${environment.apiDevUrl}/restaurant/category`,
        headers: {'Content-Type': 'application/json'},
        data: {
          category: item
        }
      })
      this.setState({restaurantData: res.data})
      console.log('restaurantData : ', this.state.restaurantData);
      return res.data
    } catch (error) {
      console.error(error);
    }
  }

  onPressCategoryItem = item => {
    this.getRestaurantByCategories(item.title)
  }

  onPressRestaurantItem = item => {
    this.props.navigation.navigate('RestaurantDetailScreen', {item})
  }

  initCartFromPersistentStore() {
    AsyncStorage.getItem('@MySuperCart:key')
      .then(res => {
        if (res != null) {
          const array = JSON.parse(res)
          console.log(array)
          this.props.navigation.dispatch({type: 'Override', items: array})
        }
      })
      .catch(error => {
        console.log(`Promise is rejected with error: ${error}`)
      })
  }

  renderCategoryItem = ({item}) => (
    <TouchableHighlight onPress={() => this.onPressCategoryItem(item)}>
      <View style={styles.categoryItemContainer}>
        <ItemCategory image={item.image} title={item.title} />
      </View>
    </TouchableHighlight>
  )

  renderRestaurantItem = ({item}) => (
    <TouchableHighlight onPress={() => this.onPressRestaurantItem(item.restaurant.id)}>
      <View style={styles.foodItemContainer}>
        <ItemRestaurant
          // id={item.restaurant.id}
          image={item.restaurant.image}
          title={item.restaurant.nom}
          distance={item.distance}
          categories={item.restaurant.categorie}
        />
      </View>
    </TouchableHighlight>
  )

  render() {
    console.log('dans le render : ', this.state.categories);
    // const categoryFromList = this.props.navigation.state.params.itemCategory
    // console.log('category dans homescreen : ',categoryFromList);
    return (
      <ScrollView style={styles.container}>
        <Text style={styles.title}> Catégories populaires</Text>
        <View style={styles.categories}>
          <FlatList
            horizontal
            initialNumToRender={4}
            data={categoriesData}
            showsHorizontalScrollIndicator={false}
            renderItem={this.renderCategoryItem}
            keyExtractor={item => `${item.id}`}
          />
        </View>
        <Text style={styles.title}> Restaurants </Text>
        <View style={styles.foods}>
          <FlatList
            initialNumToRender={2}
            data={this.state.restaurantData}
            renderItem={this.renderRestaurantItem}
            keyExtractor={item => `${item.restaurant.id}`}
          />
        </View>
      </ScrollView>
    )
  }
}

HomeScreen.propTypes = {
  navigation: PropTypes.shape({
    navigate: PropTypes.func.isRequired,
  }),
}


/*End HomeScreen*/

标签: reactjsreact-nativenavigation

解决方案


最简单的方法是添加Lodash模块并执行以下操作:

import _ from 'lodash'

....
this.state = {
  categories: _.get(this.props, 'navigation.state.params.itemCategory'),
  restaurantData: []
}
...

这样你的应用程序就不会崩溃。


推荐阅读