我想在抽屉导航中使用上下文 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/