React Native 如何处理在另一个屏幕中获取的数据?

wz8daaqr  于 2023-04-12  发布在  React
关注(0)|答案(1)|浏览(142)

在我的react本地博览会项目中,在MainTabNavigator中,

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import TablesScreen from '../screens/Tables';
import MenuScreen from '../screens/Menu';
import AboutUsScreen from '../screens/AboutUs';
import { FontAwesome5 } from '@expo/vector-icons';
  
const Tab = createBottomTabNavigator();

const MainTabNavigator = () => {
  return (
    <Tab.Navigator
      initialRouteName="Tables"
      activeColor='#f0f'
      inactiveColor='#555'
      screenOptions={({route}) => ({
          headerShown: false,
          tabBarActiveTintColor:"#320952",         
          tabBarInactiveTintColor:"white",         
          tabBarLabelStyle: { 
            fontSize: 20 
          },
          tabBarStyle:{
            backgroundColor:"#5e0acc"
          },
          tabBarActiveBackgroundColor:"#2596be",   
          tabBarIcon:({focused, size, color}) => {
          let iconName;
          if( route.name === 'Tables') {
              iconName = 'home';
          } else if (route.name === 'Menu') { 
              iconName = 'bed';
          } else {
              iconName = 'spa'
          }
          color = focused ? "#f31282" : "#555";
          size = focused ? 28 : 24;
            return <FontAwesome5 name={iconName} size={size} color={color}/>;
          },
      })}
    >
      <Tab.Screen name="Tables" component={TablesScreen} />
      <Tab.Screen name="Menu" component={MenuScreen} />
      <Tab.Screen name="AboutUs" component={AboutUsScreen} />
    </Tab.Navigator>
  );
};

export default MainTabNavigator;

TablesScreen和MenuScreen在一个TabNavigator中,在TablesScreen中,

import React,{useEffect} from "react";
import { StyleSheet, View, Text, Image, FlatList } from "react-native";
import { useDispatch, useSelector } from "react-redux";
import { createOrder, selectOrders } from "../redux/slices/ordersSlice";
import { addDishes, selectDishes } from "../redux/slices/dishesSlice";
import { useNavigation } from "@react-navigation/native";
import { Divider } from "react-native-elements";
import { client, DISHES_QUERY } from "../Gloabls/netRequest";
import { DISH_TYPES } from "../Gloabls/constants";
import TableCard from "../components/TableCard";

const TablesScreen = () => {
  const numOfTables = 30;
  const tableNumbers = Array.from({length: numOfTables}, (_, index) => index + 1);

  const dispatch = useDispatch();
  const navigation = useNavigation();

  // should use [dispatch] or []?
  useEffect(() => {
    try {
      client.request(DISHES_QUERY).then((data) => {
        dispatch(addDishes(data.dishes));
        console.log("data dishes are", data.dishes);
      });      
    } catch (error) {
      console.log(error);
    }
  }, [dispatch]);
  
  const orders = useSelector(selectOrders);
  const dishes = useSelector(selectDishes);

  const getDishById = (dishId) => {
    return dishes.find((dish) => dish.id === dishId);
  }
  
  const renderTableItem = ({item}) => {
    const tableOrder = orders.find(order => order.tableNumber === item);

    if(tableOrder) {
      const totalAmount = tableOrder.haveBeenPlacedDishes.reduce(
        (acc,dish) => acc + getDishById(dish.dishId).price * dish.quantity,0
      );
      return (      
          <TableCard tableNumber={item} totalAmount={totalAmount} tableStatus={Boolean(tableOrder)} />
        )
    } else {
      return (
          <TableCard tableNumber={item} totalAmount={0} />
      );
    }

  };

  return (
    <View style={styles.container}>
      <View style={styles.headContainer}>
        <Image 
          source={require("../assets/logo.png")}
          resizeMode="contain"
          style={styles.headerImage}
        />
        <Text style={styles.headerText}>
          Welcome to WhatsMenu
        </Text>
      </View>
      <Divider width={1} color="white" />
      <FlatList
        data={tableNumbers}
        numColumns={5}
        renderItem={renderTableItem}
        keyExtractor={(item) => item.toString()}
      />
    </View>
  );
}

const styles=StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor:"white",
    justifyContent:"center",
  },
  headContainer:{
    flex:1,
    flexDirection:"row",
    paddingHorizontal:40,
    marginTop:60,
    marginBottom:40,
    justifyContent:"flex-start",
    alignItems:"center",
    height:100
  },
  headerImage:{
    aspectRatio: 1,
    width: "5%",
  },
  headerText:{
    fontSize:24,
    minHeight:50,
    paddingLeft:30,
    lineHeight:60,
    color: "#f31282"
  }
})

export default TablesScreen;

我在useEffect和dispatch(addDished(data.dishes))中获取菜肴数据,将菜肴添加到存储中。在dishesSlice中,

import { createSlice, createSelector } from '@reduxjs/toolkit';

const initialState = {
  dishes: [],
};

const dishesSlice = createSlice({
  name: 'dishes',
  initialState,
  reducers: {
    addDishes: (state, action) => {
      state.dishes = action.payload;
      console.log("state dishes are", state.dishes);
    },
  },
});

export const { addDishes } = dishesSlice.actions;
export const selectDishes = (state) => state.dishes;
export const selectDishesByType = (state, type) => {
  return state.dishes.filter((dish) => dish.type === type);
};

export default dishesSlice.reducer;

然后我想在菜单屏幕中使用dishesByType

import React,{ useEffect, useState} from "react";
import { StyleSheet, View, Text, Dimensions, FlatList, Image } from "react-native";
import { client, DISHES_QUERY } from "../Gloabls/netRequest";
import { DISH_TYPES } from "../Gloabls/constants";
import DishCard from "../components/DishCard";
import { Divider } from '@rneui/themed';
import { useSelector, useDispatch } from "react-redux";
import { createOrder, selectCurrentOrder, selectCurrentTable } from "../redux/slices/ordersSlice";
import { selectDishes, selectDishesByType } from "../redux/slices/dishesSlice";
import ShoppingCart from "../components/ShoppingCart";

const MenuScreen = () => {
  const [dishesByType, setDishesByType] = useState([]);
  const dispatch = useDispatch();
  const dishes = useSelector(selectDishes);

  useEffect(() => {
    console.log("dishes in menuscreen are", dishes);
    const filterByDishesTypeArr = dishes.filter((dish) => dish.type == "main");
    setDishesByType(filterByDishesTypeArr);   
  }, [dispatch]);

  const currentTableNum = useSelector(selectCurrentTable);
  const dishesCountInShoppingCart = (useSelector(selectCurrentOrder)).tobeAddedDishes.length;

  const renderDishItem = ({item}) => {
      return (
        <DishCard 
          dish={item}
        />
      );
  };

  return (
    <View style={styles.container}>
      <View style={styles.headerContainer}>
        <Image
          source={require("../assets/table.png")}
          resizeMode="contain"
          style={styles.headerImage}
        />
        <Text style={styles.headerText}>
          Table {currentTableNum}
        </Text>
        <ShoppingCart style={styles.headerCart} count={dishesCountInShoppingCart}/>
      </View>
      <Divider width={1.5} color={"white"} />
      <View style={styles.flatlistContainer}> 
        <FlatList
          data={dishesByType}
          numColumns={5}
          width={Dimensions.get('window').width}
          style={styles.flat_list}
          alignItems={dishesByType.length > 1 ? "flex-start":"center"}
          renderItem={renderDishItem}
        />    
      </View>
    </View>
  );
}

const styles = StyleSheet.create({

  container:{
    flex:1,
    backgroundColor:"#5e0a9c"
  },
  headerContainer:{

    flex:1,
    flexDirection:"row",
    paddingHorizontal:40,
    marginTop:60,
    marginBottom:40,
    justifyContent:"space-between",
    alignItems:"center",
    height:100
  },
  headerImage:{
    aspectRatio: 1,
    width: "5%",
  },
  headerText: {

    textAlign: 'center',
    fontSize: 30,
    minHeight:50,

  },
  shoppingcart:{

  },
  flatlistContainer:{
    paddingTop: 20,
    justifyContent:"flex-start",
    alignItems:"center"
  },
  flat_list: {
    height: 700,
    flexGrow: 0,
    paddingHorizontal: 20,
  },
});

export default MenuScreen;

错误是
菜单屏幕中的LOG菜肴为{“菜肴”:[]} ERROR TypeError:undefined不是函数。
这意味着(在我看来),MenuScreen在客户端之前初始化。request(DISHES_QUERY).then((data)=〉{...}这是异步的,需要更多的“时间”,所以盘子还没有准备好。
在这种情况下,我如何在MenuScreen中正确使用dishesByType?我不想再次重新获取菜肴数据,因为它在整个应用生命周期中是不可变的?我们有更好的解决方案吗?

0ve6wy6x

0ve6wy6x1#

export const selectDishesByType = (state, type) => {
  return state.dishes.dishes.filter((dish) => dish.type === type);
};

现在,它是确定的,因为state.discries.discries.is一个数组。我应该小心数据细节。

相关问题