React Native:如何将数据从屏幕传递到另一个屏幕?

时间:2020-07-20 11:07:42

标签: javascript reactjs react-native

我的AuthNavigator中的

是onAuthChanged,因此当有人登录时它会呈现我的AppStack。现在,我需要在“成分”屏幕中从已登录人员那里获得用户ID。这个成分屏幕是Tabnavigator内部的Stacknavigator。因此,如何将数据从用户var传递到“成分”屏幕。

AuthNavigator文件:

import React, { useState, useEffect, createContext } from "react";
import firebase from "./firebase";
import AppStack from "./stacks/AppStack";
import AuthStack from "./stacks/AuthStack";


export const AuthContext = createContext(null);


export default function AuthNavigator() {
  const [initializing, setInitializing] = useState(true);
  const [user, setUser] = useState(true);

  // Handle user state changes
  async function onAuthStateChanged(result) {
    setUser(result);
    if (initializing) setInitializing(false);
    console.log(user.uid)
    var userDoc = await firebase.firestore().doc("users/" + user.uid).get();
    if (!userDoc.exists) {
      await userDoc.ref.set({
        email: user.email,
        uid: user.uid
      })
    }
  }

  useEffect(() => {
    const authSubscriber = firebase
      .auth()
      .onAuthStateChanged(onAuthStateChanged);
    // unsubscribe on unmount
    return authSubscriber;
  }, []);

  if (initializing) {
    return null;
  }

  return user ? (
    <AuthContext.Provider value={user}>
      <AppStack user={user} />
    </AuthContext.Provider>
  ) : (
      <AuthStack />
    );
}

AppStack

import React, { lazy } from "react";
import News from "../screens/News";
import Favorites from "../screens/Favorites";
import NewRecipe from "../screens/NewRecipe";
import Ingredients from "../screens/Ingredients";
import Profile from "../screens/Profile";
import { NavigationContainer, DarkTheme } from "@react-navigation/native";
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { MaterialIcons } from "@expo/vector-icons";
import { createStackNavigator } from "@react-navigation/stack";
import { AuthContext } from "../AuthNavigator"



export default function AppStack() {
  const Tab = createBottomTabNavigator();
  const NewsStack = createStackNavigator();
  const FavoritesStack = createStackNavigator();
  const NewRecipeStack = createStackNavigator();
  const IngredientsStack = createStackNavigator();
  const ProfileStack = createStackNavigator();



  function NewsNav() {
    return (
      <NewsStack.Navigator>
        <NewsStack.Screen
          name="News"
          component={News}
          options={{
            headerTintColor: "#AD1457",
            headerStyle: {
              backgroundColor: "#171717",
              height: 75,
            },
            headerTitleStyle: {
              marginTop: -15,
            },
          }}
        />
      </NewsStack.Navigator>
    );
  }

  function FavoritesNav() {
    return (
      <FavoritesStack.Navigator>
        <FavoritesStack.Screen
          name="Favoriten"
          component={Favorites}
          options={{
            headerTintColor: "#AD1457",
            headerStyle: {
              backgroundColor: "#171717",
              height: 75,
            },
            headerTitleStyle: {
              marginTop: -15,
            },
          }}
        />
      </FavoritesStack.Navigator>
    );
  }

  function NewRecipeNav() {
    return (
      <NewRecipeStack.Navigator mode="card">
        <NewRecipeStack.Screen
          name="Neue Rezepte"
          component={NewRecipe}
          options={{
            headerTintColor: "#AD1457",
            headerStyle: {
              backgroundColor: "#171717",
              height: 75,
            },
            headerTitleStyle: {
              marginTop: -15,
            },
          }}
        />
      </NewRecipeStack.Navigator>
    );
  }

  function IngredientsNav(props) {
    return (
      <IngredientsStack.Navigator>
        <IngredientsStack.Screen
          name="Zutaten"
          component={Ingredients}
          options={{
            headerTintColor: "#AD1457",
            headerStyle: {
              backgroundColor: "#171717",
              height: 75,
            },
            headerTitleStyle: {
              marginTop: -15,
            },
          }}
        />
      </IngredientsStack.Navigator>
    );
  }

  function ProfileNav() {
    return (
      <ProfileStack.Navigator >
        <ProfileStack.Screen
          name="Profil"
          component={Profile}
          options={{
            headerTintColor: "#AD1457",
            headerStyle: {
              backgroundColor: "#171717",
              height: 75,
            },
            headerTitleStyle: {
              marginTop: -15,
            },
          }}
        />
      </ProfileStack.Navigator >
    );
  }
  return (
    <NavigationContainer>
      <AuthContext.Consumer value={user}>
        <Tab.Navigator
          tabBarOptions={{
            style: {
              backgroundColor: '#171717',
              borderTopColor: '#121212'
            },
            inactiveTintColor: '#fff',
            activeTintColor: '#AD1457',
          }}
          initialRouteName="News"
          screenOptions={({ route }) => ({
            tabBarIcon: ({ color }) => {
              let iconName;

              if (route.name == "News") {
                iconName = "language";
              } else if (route.name == "Favoriten") {
                iconName = "star-border";
              } else if (route.name == "Hinzufügen") {
                iconName = "add-circle-outline";
              } else if (route.name == "Zutaten") {
                iconName = "shopping-cart";
              } else if (route.name == "Profil") {
                iconName = "person";
              }
              return (
                <MaterialIcons
                  name={iconName}
                  color={color}
                  size={25}
                ></MaterialIcons>
              );
            },
          })}
        >
          <Tab.Screen name="News" component={NewsNav} />
          <Tab.Screen name="Favoriten" component={FavoritesNav} />
          <Tab.Screen name="Hinzufügen" component={NewRecipeNav} />
          <Tab.Screen name="Zutaten" component={IngredientsNav} />
          <Tab.Screen name="Profil" component={ProfileNav} />
        </Tab.Navigator>
      </AuthContext.Consumer>
    </NavigationContainer >
  );
}

成分屏幕文件:

import React, { useState } from "react";
import { View, Text, StyleSheet, TextInput, ImageBackground, ActivityIndicator } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { FlatList, TouchableOpacity } from "react-native-gesture-handler";
import { AntDesign, Ionicons, Feather } from '@expo/vector-icons';
import firebase from "../firebase"
import { user } from '../AuthNavigator'

export default function Ingredients(props) {

  const [isLoading, setIsLoading] = useState(false);

  const ingredientsList = [
  ]

  const [userIngredientsList, setUserIngredientsList] = useState(ingredientsList);

  function handleRemoveItem(id, label) {
    const newList = userIngredientsList.filter((item) => item.id !== id);
    setUserIngredientsList(newList);
    window.alert("Die Zutat " + (label) + " wurde gelöscht")
  }

  var appId = "20b96f8f",
    appKey = "aebde7ed85b4aec1f50d3cbe4ff4f165";


  async function fetchIngredient(searchValue) {
    setIsLoading(true);
    var request = new XMLHttpRequest();
    request.open("GET", "https://api.edamam.com/api/food-database/v2/parser?app_id=" + appId + "&app_key=" + appKey + "&ingr=" + searchValue);
    request.addEventListener('load', function (event) {
      if (request.status >= 200 && request.status < 300) {
        var food = JSON.parse(request.responseText).parsed[0].food;
        console.log(user.uid)
        var newItem = {
          id: food.foodId,
          label: searchValue,
          image: food.image,
          amount: 1
        };
        var found = false
        userIngredientsList.forEach((item, index) => {
          if (item.id == newItem.id) {
            newItem.amount = item.amount + 1
            userIngredientsList.splice(index, 1)
          }
        })
        setUserIngredientsList(ingredientsList => [newItem, ...ingredientsList]);
        setIsLoading(false);
        setSearchValue('');


        firebase.firestore().doc("ingredients/" + props.user.uid).set({
          ingredients: userIngredientsList
        })
      }
      else {
        setIsLoading(false);
        window.alert('Gibt es nicht')
      }
    });
    request.send();
  }

  const renderItem = ({ item }) => (
    <View style={styles.item} >
      <View>
        <ImageBackground source={{ uri: item.image }}
          style={styles.itemBackground}
          imageStyle={{ borderTopRightRadius: 18, borderBottomRightRadius: 18, opacity: 0.4 }}
          resizeMode="cover">
          <TouchableOpacity onPress={() => handleRemoveItem(item.id, item.label)}>
            <AntDesign style={styles.iconDelete} name="delete" size={30} color="black" />
          </TouchableOpacity>
        </ImageBackground >
      </View>
      <View style={styles.itemInfo}>
        <Text style={styles.itemTitle}>{item.title}</Text>
        <Feather style={styles.iconTime} name="clock" size={30} color='#fff' />
        <Text style={styles.itemCookingTime}>~ {item.time} min</Text>
        <Text style={{ color: '#fff' }}>{item.amount} </Text>
      </View>
    </View >
  )



  const [searchValue, setSearchValue] = useState('');


  return (
    <View style={styles.container}>
      <View style={styles.searchBar}>
        <View style={{ alignSelf: "flex-end", marginTop: 8, marginRight: 30 }}>
          <TouchableOpacity onPress={async () => await fetchIngredient(searchValue)}>
            {!isLoading && <Ionicons name="md-add" size={32} color="#fff" />}
          </TouchableOpacity>
          {isLoading && <ActivityIndicator style={styles.loading} color='#AD1457' />}
        </View>
        {!isLoading && <TextInput style={{
          alignSelf: "flex-start", marginLeft: 25, marginTop: -30, fontSize: 20, color: '#fff', width: 200
        }} placeholder="Suche" placeholderTextColor='#fff' value={searchValue} onChangeText={(searchValue) => setSearchValue(searchValue)}></TextInput>}

      </View>

      <FlatList
        data={userIngredientsList}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}>
      </FlatList>
    </View >
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "#121212",
  },
  item: {
    flex: 1,
    width: 350,
    height: 200,
    marginTop: 50,
    alignSelf: "center",
    borderWidth: 2,
    borderRadius: 20,
    borderColor: '#AD1457'
  },
  itemBackground: {
    width: 174,
    height: 196,
    alignSelf: "flex-end",
    backgroundColor: 'rgba(255,255,255,0.2)',
    borderTopRightRadius: 18,
    borderBottomRightRadius: 18
  },
  itemInfo: {
    marginTop: -174,
    width: 174,
    height: 196,
    alignSelf: "flex-start",
    borderTopRightRadius: 18,
    borderBottomRightRadius: 18
  },
  itemTitle: {
    color: '#fff',
    fontSize: 18,
    alignSelf: "flex-start",
    marginLeft: 35
  },
  iconTime: {
    alignSelf: "flex-start",
    marginLeft: 35,
    marginTop: 75
  },
  itemCookingTime: {
    marginLeft: 80,
    fontSize: 18,
    color: '#fff',
    marginTop: -30
  },
  iconDelete: {
    alignSelf: "flex-end",
    marginRight: 25,
    marginTop: 25,
    color: '#fff'
  },
  checkCircle: {
    alignSelf: "flex-end",
    marginRight: 25,
    marginTop: 85,
    color: "#00FF44"
  },
  searchBar: {
    backgroundColor: '#313131',
    width: 325,
    height: 50,
    borderRadius: 25,
    color: '#fff',
    fontSize: 20,
    marginTop: 25
  },
  loading: {
    alignSelf: "flex-end",
    marginTop: 8,
  }
});

1 个答案:

答案 0 :(得分:0)

我只用了useContext(AuthContext);