简体   繁体   English

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

[英]How to use ContextAPI in navigation drawer in React Native?

I want to use context API in the navigation drawer and I am stuck in how to do that?我想在导航抽屉中使用上下文 API 并且我被困在如何做到这一点?

I have two screens Display screen and upload screen, in upload screen i am collecting data and sending them to useState hooks and then onlick sending them to display screen.我有两个屏幕显示屏幕和上传屏幕,在上传屏幕中我正在收集数据并将它们发送到 useState 挂钩,然后 onlick 将它们发送到显示屏幕。 in display screen ia adding this data into array now problem is when i go back upload screen again to send more data display screen array gets return to it's initial state which is empty.在显示屏 ia 中,现在将此数据添加到数组中,问题是当我 go 再次返回上传屏幕以发送更多数据时,显示屏数组返回到它的初始 state,它是空的。 Now i need to create a context api so that i can add data in it.现在我需要创建一个上下文 api 以便我可以在其中添加数据。 How can i do that.我怎样才能做到这一点。 Below is my code:下面是我的代码:

/**
 * 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

Upload.js上传.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

Display.js显示.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

my Context.js我的 Context.js

import React from "react"

const MyContext = React.createContext({})

export default MyContext

Here is the link for more about context (works no differently in navigation components): https://reactjs.org/docs/context.html这是有关上下文的更多信息(在导航组件中的工作方式没有什么不同)的链接: https://reactjs.org/docs/context.html

Now, context is overkill for what you are trying to do.现在,上下文对于您正在尝试做的事情来说太过分了。 What you're doing now is fine for the most part (though hard to read).你现在所做的大部分都很好(虽然很难阅读)。 The problem, however, is that when you're using navigation, the components are rendered with the navigation container.然而,问题在于,当您使用导航时,组件是使用导航容器呈现的。 So when you call navigation.navigate("Display",MyData:fileUri}) from Upload.js, you're receiving the route data in Display.js w just an assignment operator: const Category = data["MyData"]["newCategory"] which does nothing to re-render the Display component state.因此,当您从 Upload.js 调用navigation.navigate("Display",MyData:fileUri})时,您将在 Display.js 中接收路由数据,仅使用赋值运算符: const Category = data["MyData"]["newCategory"]对重新渲染显示组件 state 没有任何作用。

One way to implement this is to put the data in a useState hook in the Display component so the component knows when to update it.实现这一点的一种方法是将数据放入 Display 组件的 useState 挂钩中,以便组件知道何时更新它。 Also, since the route data is not initialized when you navigate to Display.js ( navigation.navigate... ) from Upload.js, use a useEffect hook so the component knows when to set the data:此外,由于当您从 Upload.js 导航到 Display.js ( navigation.navigate... ) 时路由数据未初始化,请使用 useEffect 挂钩,以便组件知道何时设置数据:

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

useEffect({
  const dataFromUpload = route.params;
  setData(dataFromUpload["MyData"]["data"]);
},[]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM