Converting React-Native-Draggable-View from Class to Hooks - javascript

I am attempting to write some code using React-Native-Draggable-View but the example that has it the way I want is written in "class" form, while I write everything in "Hooks/Functional" form. Here is the original part of the code written in the class format. When I try to convert it myself I am generate an error.
import React, { useState, useEffect, Component }from "react";
import Drawer from 'react-native-draggable-view'
import CheckScreen from './CheckScreen'
import ListScreen from './ListScreen'
function RunningScreen({navigation}) {
...
return(
...
<Drawer
initialDrawerSize={0.09}
renderContainerView={() => { <View style = {{flex: 1, backgroundColor: 'red'}}/> }}
renderDrawerView={() => { <View style = {{flex: 1, backgroundColor: 'red'}}/> }}
renderInitDrawerView={() => {
<View style = {{backgroundColor: '#fff', height: height*0.2}}>
<StatusBar hidden = {true}/>
<StatusBar hidden = {true}/>
</View>
)}
/>
)
}
...
export {RunningScreen}

Try below code
import React from 'react';
import {Dimensions, StatusBar, View} from 'react-native';
import Drawer from 'react-native-draggable-view';
const {height} = Dimensions.get('window');
function RunningScreen({navigation}) {
return (
<Drawer
initialDrawerSize={0.09}
renderContainerView={() => (
<View style={{flex: 1, backgroundColor: 'red'}} />
)}
renderDrawerView={() => (
<View style={{flex: 1, backgroundColor: 'red'}} />
)}
renderInitDrawerView={() => (
<View style={{backgroundColor: '#fff', height: height * 0.2}}>
<StatusBar hidden={true} />
</View>
)}
/>
);
}
export {RunningScreen};

Related

undefined is not an object (evaluating 'navigation.navigate') when trying to navigate to a file that will open camera on the phone

I'm trying to navigate to my page "CameraPage.js" but I'm getting this error "undefined is not an object (evaluating 'navigation.navigate')". Can anybody see the problem? This ismy first question here so please tell me if I can be more specific.
Here's my App.js:
import { StyleSheet, Text, View, TouchableOpacity, Pressable } from 'react-native';
import React, {useEffect, useState} from "react";
import { FontAwesome } from '#expo/vector-icons';
import { useNavigation } from '#react-navigation/native';
export default function App({ navigation }) {
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress ={() => navigation.navigate('CameraFunction')}>
<FontAwesome name="camera" size={100} color="#FFB6C1" />
</TouchableOpacity>
<Pressable>
<FontAwesome name="photo" size={100} color="#FFB6C1" />
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFDBE9'
},
buttonContainer: {
backgroundColor: 'transparent',
justifyContent: 'space-between',
},
});
Here is my CameraPage.js file:
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import {Camera, CameraType} from 'expo-camera';
import {useEffect, useState} from "react";
export default function CameraPage() {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(CameraType.back);
useEffect(() => {
(async () => {
const {status} = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
if (hasPermission === null) {
return <View/>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
<Camera style={styles.camera} type={type}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.button}
onPress={() => {
setType(type === CameraType.back ? CameraType.front : CameraType.back);
}}>
<Text style={styles.text}> Flip </Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
camera: {
flex: 1,
},
buttonContainer: {
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
margin: 20,
},
button: {
flex: 0.1,
alignSelf: 'flex-end',
alignItems: 'center',
},
text: {
fontSize: 18,
color: 'white',
},
});
Here is my navigation file:
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import {NavigationContainer} from '#react-navigation/native';
import CameraPage from "../Camera/CameraPage";
const Routes = createStackNavigator();
export default function Navigator() {
return (
<NavigationContainer>
<Routes.Navigator>
<Routes.Screen
name="CameraFunction"
component={CameraPage}
/>
</Routes.Navigator>
</NavigationContainer>
);
}
Your navigation container must be wrapped around the root of your application or otherwise the navigation object will not be passed to the components that you have defined as screens.
The following fixes your issue.
export default const App = () => {
return (
<NavigationContainer>
<Routes.Navigator>
<Routes.Screen name="Home" component={HomeScreen} />
<Routes.Screen
name="CameraFunction"
component={CameraPage}
/>
</Routes.Navigator>
</NavigationContainer>
);
}
Your HomeScreen contains the old code from App, but now you can access the navigation object since we have defined HomeScreen as a screen inside the navigator. It will be passed to that screen by the navigation framework. Notice as well that HomeScreen is the initial screen of your application.
export default function HomeScreen({ navigation }) {
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress ={() => navigation.navigate('CameraFunction')}>
<FontAwesome name="camera" size={100} color="#FFB6C1" />
</TouchableOpacity>
<Pressable>
<FontAwesome name="photo" size={100} color="#FFB6C1" />
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFDBE9'
},
buttonContainer: {
backgroundColor: 'transparent',
justifyContent: 'space-between',
},
});
Notice, that you need to navigate back to the HomeScreen once you have navigated to the CameraPage. You can use the navigation object in the CameraPage as well and trigger navigation.goBack to achieve this effect.
You just use #react-navigation/native-stack in place of #react-navigation/stack in App.js file then it will working perfect ,
import * as React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createNativeStackNavigator} from '#react-navigation/native-stack';
import Home from './TopTabBar/Home';
import 'react-native-gesture-handler';
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;

Navigation, not working from Pulled functions

I will try to explain this as best I can, I'm still new and have a hard time understanding the terminology.
I am working on a react native project. I have created two files. One Header.js and one footer.js.
I have successfully pulled them in to my Home Screen. However the buttons, inside footer.js, no longer fires. I get; undefined is not an object (evaluating 'navigation.navigate') for the error.
How do I bring back the functionality?
Any help is very appreciated. Here is my project to help;
App.js
import React from 'react';
import TabNavigator from "./assets/component/TabNavigator";
import {StackNavigation} from "./assets/component/StackNavigation";
export default function App() {
return (
<StackNavigation/>
);
}
StackNavigation.js;
import React from 'react';
import { HomeScreen} from "../Screens/HomeScreen";
import LayoutProps from "../Screens/Layout Props";
import SampleViewProps from "../Screens/SampleViewProps";
import {NavigationContainer} from "#react-navigation/native";
import {createNativeStackNavigator} from "#react-navigation/native-stack";
// import ShareExample from "./assets/component/SBShare";
const Stack = createNativeStackNavigator();
export function StackNavigation() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen}/>
<Stack.Screen name="Layout Props" component={LayoutProps} />
<Stack.Screen name="View Props" component={SampleViewProps} />
</Stack.Navigator>
</NavigationContainer>
);
}
HomeScreen.js;
import React from 'react';
import {Button, View, SafeAreaView, StyleSheet} from 'react-native';
import HeaderSB from "../component/SBHeader";
import FooterSB from "../component/SBFooter";
// import ShareExample from "./assets/component/SBShare";
export function HomeScreen({navigation}) {
const receiveValue = (value) => {
console.log("value received from B", value)
}
return (
<>
<SafeAreaView style={styles.container}>
<View style={styles.headerContainer}>
<HeaderSB receiveValue={receiveValue}>
</HeaderSB>
</View>
<View style={styles.mainContent}>
<View style={styles.buttonBox}>
<Button onPress={() => navigation.navigate('Layout Props')} title="Layout Props"/>
<Button onPress={() => navigation.navigate('View Props')} title="View Style Props"/>
</View>
</View>
<View styles={styles.footerContainer}>
<FooterSB receiveValue={receiveValue}>
</FooterSB>
</View>
</SafeAreaView>
</>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "space-between",
},
headerContainer: {
},
mainContent: {
},
buttonBox: {}
,
footerContainer: {
},
});
Footer.js;
import * as React from "react";
import {StyleSheet, TouchableOpacity, View} from "react-native";
import {AntDesign, Feather} from "#expo/vector-icons";
import {StackNavigation} from "./StackNavigation";
const FooterSB = ({navigation}) => {
return (
<>
{/* Bottom App Navigation */}
<View style={footerStyle.navCon}>
<View style={footerStyle.navBar}>
{/* Home Button */}
<TouchableOpacity style={footerStyle.home} onPress={() =>
navigation.navigate('Home')}
>
{/* Icon */}
<AntDesign name="home" size={50} color="white"/>
</TouchableOpacity>
{/* Navigation Divider */}
<View style={footerStyle.navDivider}/>
{/* Setting Button */}
<TouchableOpacity style={footerStyle.settings} onPress={() =>
navigation.navigate('Layout Props')}
>
{/* Icon */}
<Feather name="settings" size={50} color="white"/>
</TouchableOpacity>
</View>
</View>
</>
);
}
const footerStyle = StyleSheet.create({
navCon: {
flex: 1,
marginTop: 20,
alignItems: "center",
justifyContent: "flex-end"
},
navBar: {
flexDirection: "row",
justifyContent: "space-evenly",
alignItems: "center",
backgroundColor: "#808080",
width: 500,
height: 50,
},
home: {
// paddingHorizontal: 55,
},
navDivider: {
backgroundColor: "#FFF",
width: 4,
height: 50,
},
settings: {
// marginRight: 107,
// paddingHorizontal: 55,
},
});
export default FooterSB;
If you want navigation as default prop you should add it as <Stack.Screen> but as FooterSB is custom and individual component it doesn't get wrapped with navigation prop automatically.
You need to pass navigation as prop to that so change below
<FooterSB receiveValue={receiveValue}>
</FooterSB>
to
<FooterSB receiveValue={receiveValue} navigation={navigation}>
</FooterSB>
Same way you can pass navigation to header too.

Rendering another screen in react-native app

I'm experiencing trouble navigating between pages in my react native app. When I attempt to use the button, I get the following error message: TypeError: undefined is not an object (evaluating '_this.props.navigation') I have created my app using numerous js files, and id like to navigate between them using buttons. My App.js file renders to the WelcomeScreen from initializing.
import 'react-native-gesture-handler';
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import RecipesList from "cakeapp/app/screens/RecipesList.js";
import { ImageBackground, StyleSheet, View, Text, Button, navigation } from "react-native";
function WelcomeScreen(props) {
return (
<NavigationContainer>
<ImageBackground
style={styles.background}
source={require('cakeapp/app/assets/MainPage.png')}
>
<Text style={styles.text}>MyCakeRecipes</Text>
<View style={styles.homeButton}>
<Button
title="Recipes"
onPress={() => this.props.navigation.navigate('RecipesList')}
/>
</View>
</ImageBackground>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
background: {
flex:1,
justifyContent: "flex-end",
},
text: {
fontSize: 30,
fontWeight: "bold",
color: "white",
textAlign: "center",
bottom: 500,
},
homeButton: {
width: '100%',
height: 40,
backgroundColor: '#5f7f8a'
}
})
export default WelcomeScreen;
import React from 'react';
import { Image, ScrollView, View, Text, } from 'react-native';
const imageDis = {
width: 150,
height: 150
//flex:1,
//justifyContent: "flex-end"
};
const Recipes = () => (
<ScrollView style={{backgroundColor: '#5f7f8a'}}>
<Text style={{ fontSize: 20 }}>Chocolate Cake</Text>
<Image source={require('cakeapp/app/assets/Choc.png')} style={imageDis} />
<Text style={{ fontSize: 20 }}>Chocolate cupcake</Text>
<Image source={require('cakeapp/app/assets/ChocCu.png')} style={imageDis} />
<Text style={{ fontSize: 20 }}>Lemon Cake</Text>
<Image source={require('cakeapp/app/assets/Lemon.png')} style={imageDis} />
<Text style={{ fontSize: 20 }}>Lemom meringue</Text>
<Image source={require('cakeapp/app/assets/LemonM.png')} style={imageDis} />
<Text style={{ fontSize: 20 }}>Chocolate Berry</Text>
<Image source={require('cakeapp/app/assets/ChcoBerry.png')} style={imageDis} />
</ScrollView>
);
export default Recipes
As far as I know, < NavigationContainer> is used in app.js file to define the screens you want to navigate to. And you have to pass navigation as a prop to the component.
Your app.js file should look something like this
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Welcome"
component={WelcomeScreen}
/>
<Stack.Screen
name="Recipes"
component={RecipesList} />
</Stack.Navigator>
</NavigationContainer>
);
};
And your welcomeScreen like this:
const WelcomeScreen = ({ navigation }) => {
return (
<Button
title="RecipesList"
onPress={() =>
navigation.navigate('RecipesList')
}
/>
);
};
Let me know if it doesnt work

Calling navigation.navigate from another component

Today i spend 6 hours trying to figure this out, this is kind of my last resort.
I want to switch screens with react navigate. It works when all the screens are in the same file. but when i seperate them into multiple files (1 file for every screen) it gives me the error 'undefined is not an object (evaluating '_this.props.navigation.navigate')
i have tried a lot of things. hope you can help. here is the code.
App.js--------------------------------------------------
import 'react-native-gesture-handler';
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Button} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator()
// PAGES
import LandingScreen from './src/landing';
import House from './src/house';
//CODE
function HomeScreen({navigation}) {
return(
<LandingScreen navigation={this.props.navigation}/>
);
}
function HouseScreen({navigation}) {
return(
<House navigation={this.props.navigation}/>
);
}
class App extends React.Component {
render(){
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen}/>
<Stack.Screen name="House" component={HouseScreen}/>
</Stack.Navigator>
</NavigationContainer>
)
}
}
const styles = {
}
export default App;
landing.js---------------------------------------------
import React from 'react';
import {View, Text, ImageBackground, TouchableOpacity, Image} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
//IMAGES
var myBackground = require('../assets/icons/lightblueBackground.png')
var buttonbannerlower = require('../assets/icons/buttonbannerlower.png')
var talkbuttonblue = require('../assets/icons/talkbuttonblue.png')
var gearIcon = require('../assets/icons/Gearicon.png')
var playIcon = require('../assets/icons/playicon.png')
var pointerIcon = require('../assets/icons/pointerIcon.png')
var houseIcon = require('../assets/icons/houseIcon.png')
//CODE
class Landing extends React.Component{
render(){
return (
<View style={styles.container}>
<View style={{flex: 0.2, flexDirection: 'row',}}>
<ImageBackground source={buttonbannerlower} style={styles.imageBackground}>
<TouchableOpacity>
<Image source={gearIcon} style={styles.iconsLeft}/>
</TouchableOpacity>
<TouchableOpacity>
<Image source={playIcon} style={styles.iconsLeft}/>
</TouchableOpacity>
<TouchableOpacity>
<Image source={talkbuttonblue} style={styles.blueButton}/>
</TouchableOpacity>
<TouchableOpacity>
<Image source={pointerIcon} style={styles.iconPointer}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => props.navigation.navigate('House')}>
<Image source={houseIcon} style={styles.iconsRight}/>
</TouchableOpacity>
</ImageBackground>
</View>
<View style={{backgroundColor: 'green', flex: 0.2, alignItems: 'center',}}>
<Text>Hello</Text>
</View>
</View>
)
}
}
const styles = {
container: {
flex: 1,
flexDirection: 'column-reverse',
backgroundColor: '#ACE1EB'
},
imageBackground: {
width: '100%',
height: '100%',
flex: 1,
alignItems: 'flex-end',
flexDirection: 'row',
justifyContent: 'center',
alignContent: 'center',
},
blueButton: {
height: 110,
width: 110,
},
iconsLeft: {
marginRight: 20,
marginBottom: 10,
height: 40,
width: 40
},
iconsRight: {
marginLeft: 20,
marginBottom: 10,
height: 40,
width: 40
},
iconPointer: {
marginLeft: 20,
marginBottom: 10,
height: 40,
width: 40
},
}
export default Landing;
You should add screen components like this:
import LandingScreen from './src/landing';
import House from './src/house';
class App extends React.Component {
render(){
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={LandingScreen}/>
<Stack.Screen name="House" component={House}/>
</Stack.Navigator>
</NavigationContainer>
)
}
}
also to use props in a class component use this keyword:
<TouchableOpacity onPress={() => this.props.navigation.navigate('House')}>
One more thing, to access props in a class component you call constructor like this :
class Landing extends React.Component{
constructor(props) {
super(props);
}
render(){
return (
<View style={styles.container}>
<View style={{flex: 0.2, flexDirection: 'row',}}>
<ImageBackground source={buttonbannerlower} style={styles.imageBackground}>
<TouchableOpacity>
<Image source={gearIcon} style={styles.iconsLeft}/>
</TouchableOpacity>
<TouchableOpacity>
<Image source={playIcon} style={styles.iconsLeft}/>
</TouchableOpacity>
<TouchableOpacity>
<Image source={talkbuttonblue} style={styles.blueButton}/>
</TouchableOpacity>
<TouchableOpacity>
<Image source={pointerIcon} style={styles.iconPointer}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('House')}>
<Image source={houseIcon} style={styles.iconsRight}/>
</TouchableOpacity>
</ImageBackground>
</View>
<View style={{backgroundColor: 'green', flex: 0.2, alignItems: 'center',}}>
<Text>Hello</Text>
</View>
</View>
)
}
}
You don't need to create functions for the screen components. Just do it like this:
import 'react-native-gesture-handler';
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Button} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator()
// PAGES
import LandingScreen from './src/landing';
import House from './src/house';
//CODE
class App extends React.Component {
render(){
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={LandingScreen}/>
<Stack.Screen name="House" component={House}/>
</Stack.Navigator>
</NavigationContainer>
)
}
}
const styles = {
}
export default App;
Then in your screen components, use the navigation function like this to navigate to other screens.
onPress={() => this.props.navigation.navigate("House")}

App crashes when entering in screen React Native

I'm making a mobile app and then suddenly when I enter this Screen the whole app crashes. It was working before but, after I changed some style, it gave me some errors about too much Call Stack but stopped saying that and just crashes. I really don't know what's causing this. I tried to see if there was on the UseEffect() I think there is nothing there causing this.
import React, { useEffect, useState, useContext} from "react";
import {
View,
Text,
StatusBar,
TouchableOpacity,
ScrollView,
AsyncStorage,
Dimensions,
Image,
Alert,
} from "react-native";
import PlusImage from "../../../../assets/add_circle-24px.png";
import mainContext from "../../../services/contexts/mainContext";
import listContext from "../../../services/contexts/listContext";
import taskContext from "../../../services/contexts/taskContext";
import { MaterialIcons } from "#expo/vector-icons";
import styles from "./styles";
import TaskItem from "../../utils/TaskItem";
import Animated from "react-native-reanimated";
import { FlatList } from "react-native-gesture-handler";
export default function List({ route, navigation }) {
const {
clean,
getTasksList,
edited,
toogleEdited,
deleteList,
doneTasks,
todoTasks,
} = useContext(listContext);
const { taskEdited, idtask, deleteTask } = useContext(taskContext);
const [listName, setListName] = useState("");
const [screenTasks, setScreenTasks] = useState([{}]);
const [done, setDone] = useState(false);
const screenHeight = Math.round(Dimensions.get("window").height);
async function getListName() {
setListName(await AsyncStorage.getItem("listName"));
}
async function asyncGetTasks() {
await getTasksList();
}
useEffect(() => {
if (listName) getListName();
asyncGetTasks();
setScreenTasks(done ? doneTasks : todoTasks);
if (idtask) {
navigation.navigate("Task");
}
}, [edited, taskEdited, idtask, done]);
return (
<View style={styles.container}>
<StatusBar hidden />
<View style={styles.buttonsContainer}>
<TouchableOpacity
onPress={() => {
navigation.goBack();
clean();
}}
>
<MaterialIcons name="arrow-back" size={32} />
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
Alert.alert(
"Are you sure you want to delete this list?",
"",
[
{
text: "Cancel",
style: "cancel",
},
{
text: "OK",
onPress: () => {
deleteList();
clean();
navigation.goBack();
},
},
],
{ cancelable: true }
);
}}
>
<MaterialIcons name="delete" size={32} color="#bc0000" />
</TouchableOpacity>
</View>
<View style={styles.titleContent}>
<Text style={styles.titleText}>{listName}</Text>
</View>
<View style={styles.midButtonsContainer}>
<View
style={{
opacity: 1,
backgroundColor: done ? null : "#dddddd",
borderRadius: 7,
padding: 8,
opacity: 1,
}}
>
<TouchableOpacity
onPress={() => {
setDone(false);
toogleEdited();
}}
>
<Text>To do</Text>
</TouchableOpacity>
</View>
<View
style={{
opacity: 1,
backgroundColor: done ? "#dddddd" : null,
borderRadius: 7,
padding: 8,
opacity: 1,
}}
>
<TouchableOpacity
onPress={() => {
setDone(true);
toogleEdited();
}}
>
<Text style={styles.doneButton}>Done</Text>
</TouchableOpacity>
</View>
</View>
{screenTasks.length > 0 ? (
<FlatList
data={screenTasks}
renderItem={(item, index) => {
return (
<TaskItem
OnSwipeRight={() => deleteTask(item.item._id)}
{...{ item }}
/>
);
}}
/>
) : (
<View style={styles.emptyContent}>
<Text style={styles.emptyText}>This list don't have tasks yet</Text>
</View>
)}
<TouchableOpacity
style={{
position: "absolute",
top: screenHeight - 120,
right: 28,
flexDirection: "row",
width: 50,
alignSelf: "flex-end",
}}
onPress={() => {
navigation.navigate("NewTask");
}}
>
<Image source={PlusImage} />
</TouchableOpacity>
</View>
);
}
Have you tried to import it from the react lib?
import React, { useEffect } from 'react';
I don't see it in your import above.

Categories

Resources