android - 如何在 React Native 的抽屉导航中使用 ContextAPI?

标签 android reactjs react-native react-hooks react-context

我想在抽屉导航中使用上下文 API,但我不知道该怎么做?

我有两个屏幕 显示屏幕 和上传屏幕,在 上传屏幕 中,我正在收集数据并将它们发送到 useState Hook ,然后单击将它们发送到显示屏幕。在显示屏幕中,我现在将此数据添加到数组中,问题是当我再次返回上传屏幕以发送更多数据时,显示屏幕数组返回到其空的初始状态。现在我需要创建一个上下文 api,以便我可以在其中添加数据。我怎样才能做到这一点。下面是我的代码:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React from 'react';
import { StyleSheet, Text, View } from 'react-native'
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createDrawerNavigator } from '@react-navigation/drawer';
import Upload from './screens/Upload';
import Display from './screens/Display';

const Drawer = createDrawerNavigator();

const App = () => {
  return (
    <NavigationContainer>
    <Drawer.Navigator
    
    initialRouteName='Upload'
    screenOptions={{
      drawerStyle:{
        backgroundColor:"#D8BFD8",
      },
      drawerActiveBackgroundColor:"#ffffff",
      drawerActiveTintColor:"red",
      swipeEdgeWidth:300,
      drawerHideStatusBarOnOpen:true,
      headerShown:true,
      headerTitleAlign:"center",
      headerStyle:{
        backgroundColor:"#0080ff"
      },
      headerTintColor:"white",
      headerTitleStyle:{
        fontSize:25,
        fontWeight:"bold"
      }

    }}
    >
      <Drawer.Screen name="Upload" component={Upload}
      options={{
        title:"Upload Images"
      }}
      
      />
      <Drawer.Screen name="Display" component={Display}
      options={{
        title:"View Images"
      }}
      
      />
    </Drawer.Navigator>
    </NavigationContainer>
  )
}

const styles = StyleSheet.create({})

export default App

上传.js

import React, { Fragment, Component, useState,useEffect } from 'react'
import { launchCamera, launchImageLibrary } from "react-native-image-picker"
import { PermissionsAndroid, Pressable, StyleSheet, Text, View,DeviceEventEmitter } from 'react-native'
import { Header, LearnMoreLinks, Colors, DebugInstructons, ReloadInstructions } from 'react-native/Libraries/NewAppScreen'
import { TouchableOpacity } from 'react-native-gesture-handler'
import { Picker } from '@react-native-picker/picker';
import MyContext from './Context'
import { call } from 'react-native-reanimated'
import { ContinousBaseGesture } from 'react-native-gesture-handler/lib/typescript/handlers/gestures/gesture'

const Upload = ({navigation}) => {

    const [galleryData, setgallery] = useState({})
    
    const [fileUri, setfileUri] = useState({})
    const [Category, setCategory] = useState("")

    useEffect(()=>{
        setfileUri(
            prev => ({
                ...prev ,newCategory:Category
            })
        )
    },[Category])

    const onPressHandler = ()=>{

        console.log("this one Picked from picker >>>",Category)

        console.log("This one is sent to anoher screen >>>",fileUri["newCategory"])

        // DeviceEventEmitter.emit('VariableNameForListener', {MyData: fileUri})

        <MyContext.Provider value={}>
            {/* // here im stcuk  */}
            
        </MyContext.Provider>

    

        navigation.navigate("Display",{MyData:fileUri})
        // navigation.navigate("Display")
        
        // setfileUri({})
        // setCategory(null)
        
    }

    let options = {
        storageOptions: {
            skipBackup: true,
            path: 'images',
        },
    };

    const requestCameraPermission = async () => {
        try {
            const granted = await PermissionsAndroid.request(
                PermissionsAndroid.PERMISSIONS.CAMERA, {
                title: "App Camera Permission",
                message: "App needs access to your camera ",
                buttonNeutral: "Ask Me Later",
                buttonNegative: "Cancel",
                buttonPositive: "OK"

            }
            )
            if (granted == PermissionsAndroid.RESULTS.GRANTED) {
                launchCamera(options, (response) => {
                    console.log("Camera launched")

                    if (response.didCancel) {
                        console.log("Cancelled By User")
                    } else if (response.error) {
                        console.log("Image error")
                    } else if (response.customButton) {
                        alert(response.customButton)
                    } else {
                        // const source = { setfileUri(prev =>({...prev,["data"]})): response.uri }
                        setfileUri(
                            prev => ({
                                ...prev, "data": response["assets"]
                            })
                            // ...fileUri,...response
                        )
                        
                    }

                })
            }
        } catch (err) {
            console.log(err)
        }
    }

    const libraryPicker = async () => {
        try {
            const granted = await PermissionsAndroid.request(
                PermissionsAndroid.PERMISSIONS.CAMERA, {

                title: "App Camera Permission",
                message: "App needs access to your camera ",
                buttonNeutral: "Ask Me Later",
                buttonNegative: "Cancel",
                buttonPositive: "OK"

            }
            )
            if (granted == PermissionsAndroid.RESULTS.GRANTED) {
                launchImageLibrary(options, (response) => {
                    console.log("Camera launched")

                    if (response.didCancel) {
                        console.log("Cancelled By User")
                    } else if (response.error) {
                        console.log("Image error")
                    } else if (response.customButton) {
                        alert(response.customButton)
                    } else {
                        // const source = { setfileUri: response.uri }

                        console.log(JSON.stringify(response))
                    }

                })
            }
        } catch (err) {
            console.log(err)
        }
    }
    
    return (
        <View style={styles.body}>

            <View >
                <TouchableOpacity onPress={requestCameraPermission} style={styles.btnSection}>
                    <Text style={styles.text}>
                        Choose File
                    </Text>
                </TouchableOpacity>
            </View>


            <View >
                <TouchableOpacity onPress={libraryPicker} style={styles.btnSection}>
                    <Text style={styles.text}>
                        choose from Gallery
                    </Text>
                </TouchableOpacity>
            </View>

            <View>
                <Picker
                    selectedValue={Category}
                    onValueChange={(itemValue, itemIndex) =>
                        setCategory(itemValue)
                    }
                    style={styles.pickerSection}
                    dropdownIconColor={"#000"}
                    
                >
                    <Picker.Item label='Flowers' value="Flowers" ></Picker.Item>
                    <Picker.Item label='Cars' value="Cars" ></Picker.Item>
                    <Picker.Item label='Space' value="Space" ></Picker.Item>
                    <Picker.Item label='Technology' value="Technology" ></Picker.Item>
                    <Picker.Item label='Locations' value="Locations" ></Picker.Item>

                </Picker>

            </View>

            <View>
                <Pressable
                onPress={onPressHandler}
                style={[({presses}) => ({backgroundColor:presses ? "Red":"grey"}),styles.btnSection]}>
                    <Text style={styles.text}>
                        Press me 
                    </Text>

                </Pressable>

            </View>


        </View>

    )
}


const styles = StyleSheet.create({
    body: {
        flexDirection: "column",
        justifyContent: "center",
        alignItems: "center"

    },
    text: {
        color: "red",
        fontSize: 14,
        fontWeight: "bold"
    },
    btnSection: {
        width: 200,
        height: 100,
        backgroundColor: "#DCDCDC",
        justifyContent: "center",
        alignItems: "center",
        borderRadius: 50,
        margin: 20

    },
    pickerSection:{
        width:200,
        height:100,
        backgroundColor:"red",
        justifyContent:"center",
        alignItems:"center",
        borderRadius:50,
        margin:20
    },
    uploadButton:{
        width: 200,
        height: 100,
        textAlign:"center",
        alignItems:"center",
        borderRadius:50
    }

})

export default Upload

显示.js

import React, { useEffect, useState } from 'react'
import { DeviceEventEmitter, Image, StyleSheet, Text, View } from 'react-native'

const Display = ({navigation,route}) => {


    // const [data, setData] = React.useState()
    // React.useLayoutEffect(() => {
    //     DeviceEventEmitter.addListener("VariableNameForListener",emittedData=>{
    //         setData(emittedData["MyData"]["data"])
    //     })
    //     return () => {
    //         DeviceEventEmitter.removeAllListeners()
    //     };
    // }, [])

    

    const data = route.params;
    const Data = data["MyData"]["data"]

    const Category = data["MyData"]["newCategory"]
    console.log(Data,Category)

    //now what we have to do we need to create an object and for values we will use [] to keep on adding data if there is new data added

    let myObj = [
        {  Locations:[] },
        { Cars:[] },
        { Space:[] },
        { Technology:[] },
        { Flowers:[] },

    ]

    for (let i = 0;i<myObj.length;i++){
        console.log(">>",Object.keys( myObj[i])[0])

        if ( Object.keys( myObj[i])[0]===Category){
            myObj[i][Category].push(Data[0].uri)
        }
    }

    console.log(data)    

    return (
        <View>
            {/* <Image 
            source={{uri:Data[0].uri}}
            style={{ width: 500, height: 500 }}
            ></Image> */}


            <Text>okk</Text>
        </View>
    )
}
const styles = StyleSheet.create({})

export default Display

我的 Context.js

import React from "react"

const MyContext = React.createContext({})

export default MyContext

最佳答案

以下是有关上下文的更多信息的链接(在导航组件中的工作方式没有不同):https://reactjs.org/docs/context.html

现在,上下文对于您想要做的事情来说是多余的。您现在所做的大部分都很好(尽管很难阅读)。然而,问题在于,当您使用导航时,组件是使用导航容器呈现的。调用navigation.navigate("Display",MyData:fileUri}) Upload.js 中的内容不会重新渲染 Display 组件状态。

实现此目的的一种方法是仅使用赋值运算符来接收路线数据: const Category = data["MyData"]["newCategory"] ,在 Display 组件中使用 useState Hook ,以便它知道何时更新屏幕。此外,由于当您从 Upload.js 导航到 Display.js ( navigation.navigate... ) 时,路由数据尚未初始化,因此您可以使用导航的焦点监听器 Hook ,以便组件知道更新状态:

const [data, setData] = useState({});

navigation.addListener('focus', () => {
  const dataFromUpload = route.params;
  setData(dataFromUpload["MyData"]["data"]);
});

关于android - 如何在 React Native 的抽屉导航中使用 ContextAPI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70392157/

相关文章:

android - 强制停止(杀死)应用程序后是否有可能在Android应用程序中获取位置更新

java - 关于Android中BitmapFactory.Options的问题

android - Firebase 发送推送通知两次

php - Android - Web 服务、php 与 ASP.NET、XML 与 JSON?

react-native - redux 状态更新缓慢

javascript - redux 状态不会改变

javascript - 在 Firefox 中处理 keydown 失败

unit-testing - 如何测试一个 React 组件是否包含另一个带有 Tape 和 Enzyme 的组件?

reactjs - env-cmd 错误 : Failed to find . 路径中的 env 文件

react-native - react native 构建成功,但 "No devices are booted."