在我的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?我不想再次重新获取菜肴数据,因为它在整个应用生命周期中是不可变的?我们有更好的解决方案吗?
1条答案
按热度按时间0ve6wy6x1#
现在,它是确定的,因为state.discries.discries.is一个数组。我应该小心数据细节。