Hi I am a new React user and I am trying to add the following component to an app I'm developing:
import React, { useState, useEffect, Component } from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Camera, CameraType } from 'expo-camera';
function InAppCamera() {
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',
},
});
export default InAppCamera;
I am trying to reference this component in another .js file as seen below:
<FAB style={styles.fab} small icon="camera" onPress={InAppCamera} />
I get an error for an invalid hook call. Any suggestions would be great thank you so much!
//You can get some idea from the given sample.
const [showCamera, setCamera] = useState(false);
return <View>
/*Other Code If any */
<FAB style={styles.fab} small icon="camera" onPress={() => setCamera(!showCamera)} />
{showCamera ? <InAppCamera /> : null}
/*Other Code If any */
</View>
Related
I am developing react-native app for quite sometimes. During my development, almost everyday i am facing some error/warning. Among them, the most comment error I've faced is this-> Warning: Can't perform a React state update on an unmounted component. I've searched everywhere, but couldn't find a proper solution. And this log also not explaining that much. So is there anyone who can explain this which will be much more understandable, or point me out where should I dig into to solve this error or what more should I study to understand the situation. Here is the full screenshot of this error.
. And Here is the some code of one of my component:
//packages
import React, { useContext, useEffect, useState } from 'react';
import { ActivityIndicator, ImageBackground, Pressable, StyleSheet, Text, View } from 'react-native';
// third pirty packages
import { Button, HamburgerIcon, Menu, NativeBaseProvider, useToast } from 'native-base';
import Feather from 'react-native-vector-icons/Feather';
import Foundation from "react-native-vector-icons/Foundation";
import NetInfo from "#react-native-community/netinfo";
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
listenOrientationChange as lor,
removeOrientationListener as rol
} from 'react-native-responsive-screen';
//assets and components
import { AuthContext } from './../context';
const MainBody = (props) => {
const { signOut } = useContext(AuthContext);
const [isLoading, setIsLoading] = useState(false);
const toast = useToast();
useEffect(() => {
lor();
return () => {
rol();
};
}, []);
const styles = StyleSheet.create({
wrapperView: {
height: hp('87%'),
paddingTop: hp('7%'),
alignItems: 'center',
backgroundColor: '#fff'
},
dashboardView: {
width: '80%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: hp('3%')
},
dashboardCategory: {
width: '45%',
height: hp('20%'),
borderRadius: 5,
elevation: 5,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
backgroundColor: '#FFFFFF'
},
iconStyle: {
color: 'grey',
fontSize: hp('5%'),
alignSelf: 'center'
},
buttonText: {
marginTop: 10,
color: '#4b2e80',
width: '100%',
textAlign: 'center',
fontSize: hp('2.7%')
},
headerButtonView: {
position: 'absolute',
top: hp('3%'),
right: wp('5%')
}
});
return (
<View>
<View style={styles.wrapperView}>
<View style={styles.dashboardView}>
<Button light style={styles.dashboardCategory}>
<Feather style={styles.iconStyle} name="users" />
<Text style={styles.buttonText}> Clip </Text>
</Button>
<Button light style={styles.dashboardCategory}>
<Foundation style={styles.iconStyle} name='pound' />
<Text style={styles.buttonText}> Balancing </Text>
</Button>
</View>
</View>
<View style={styles.headerButtonView}>
<Menu
trigger={(triggerProps) => {
return (
<Pressable accessibilityLabel="More options menu" {...triggerProps}>
<HamburgerIcon color="#fff" />
</Pressable>
)
}}
>
<Menu.Item onPress={() => signOut()}>Logout</Menu.Item>
</Menu>
</View>
</View>
);
}
export const DashboardScreen = ({ navigation }) => {
return (
<NativeBaseProvider>
<MainBody navigate={navigation.navigate} />
</NativeBaseProvider>
);
}
we need to unsubscribe the particular subscription before our components unmounts. it's a workaround but will get rid of the error.
useEffect(() => {
let mounted = true
if(mounted){
lor();
}
return () => {
rol();
mounted= false
};
}, []);
I'm trying to make an app where I can add item in a flatlist . Then each item I can navigate to a new page only for that specific item . In that page, I can add another flatlist.
To explain it more, lets say I add few Classroom item in the flatlist (Classroom A, Classroom B, Classroom C). When I press Clasroom A , it will navigate to a page named Classroom A . In that page, I can add and delete the name of each students using another flatlist.
How can I design the page for the Classsrooms ??? Because when I add the name of the student in classroom A, the names of the students is also available in the flatlist of other Classrooms.
This is my code for the Main Menu:
import React, { useState , useEffect } from 'react';
import {
View,
Text,
TouchableOpacity,
FlatList,
Alert,
TextInput,
StyleSheet,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import AsyncStorage from '#react-native-async-storage/async-storage';
import { useNavigation } from '#react-navigation/native';
export default function MainMenu(){
const [classroomInput, setClassroomInput] = useState('');
const [classroom, setClassroom] = useState([]);
const navigation = useNavigation();
useEffect(() => {
getClassroom();
}, []);
useEffect(() => {
saveClassroom(classroom);
}, [classroom]);
const saveClassroom = async (classroom) => {
try {
const stringifyClassroom = JSON.stringify(classroom);
await AsyncStorage.setItem('classroom', stringifyClassroom);
} catch (error) {
console.log(error);
}
};
const getClassroom = async () => {
try {
const classrooms = await AsyncStorage.getItem('classroom');
if (classrooms !== null) {
setClassroom(JSON.parse(classrooms));
}
} catch (error) {
console.log(error);
}
};
const addClassroom = () => {
if (classroomInput === ''){
Alert.alert('Error', 'Please input class');
} else {
const newClassroom = {
id: Math.random().toString(),
Classroom: classroomInput,
};
setClassroom([...classroom,newClassroom]);
setClassroomInput('');
}
};
const deleteClassroom = (classroomId) => {
const newClassrooms = classroom.filter(item => item.id !== classroomId);
setClassroom(newClassrooms);
};
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder={'Add Classrooms'}
value={classroomInput}
onChangeText={(text) => setClassroomInput(text)}
/>
<TouchableOpacity onPress={() => addClassroom()} style={styles.button}>
<Text>Add Classroom</Text>
</TouchableOpacity>
<FlatList
style={styles.flatlist}
data={classroom}
keyExtractor = { (item) => item.id.toString() }
renderItem={({ item }) => (
<TouchableOpacity onPress= {() => navigation.navigate('Classroom', item)} >
<View style={styles.listItem}>
<View>
<Text style={[styles.classText , {fontSize: 18}]}>
{item?.Classroom}
</Text>
</View>
<View >
<TouchableOpacity style={[styles.delete ]} onPress={() => deleteClassroom(classroom?.id)}>
<Icon name="remove" size={15} color={'#fff'} />
</TouchableOpacity>
</View>
</View>
</TouchableOpacity>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
},
input: {
width: '70%',
borderBottomWidth: 1,
marginBottom: 20,
},
button: {
backgroundColor: 'lightblue',
padding: 10,
marginBottom: 10,
},
delete: {
backgroundColor: '#ff3333',
padding: 5,
color: '#fff',
borderWidth: 1,
borderColor: '#ff9999',
borderRadius: 5,
},
listItem: {
flexDirection: 'row',
justifyContent: 'space-between',
width: '70%',
alignItems: 'center',
},
});
And this is the code for the classroom:
/* eslint-disable prettier/prettier */
import React, { useState , useEffect } from 'react';
import {
View,
Text,
TouchableOpacity,
FlatList,
Alert,
TextInput,
StyleSheet,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import AsyncStorage from '#react-native-async-storage/async-storage';
const Classroom = ( {navigation, route}) => {
const [studentInput, setStudentInput] = useState('');
const [student, setStudent] = useState([]);
useEffect(() => {
getStudent();
}, []);
useEffect(() => {
saveStudent(student);
}, [student]);
const saveStudent = async (student) => {
try {
const stringifyStudent = JSON.stringify(student);
await AsyncStorage.setItem('student', stringifyStudent);
} catch (error) {
console.log(error);
}
};
const getStudent = async () => {
try {
const students = await AsyncStorage.getItem('student');
if (students !== null) {
setStudent(JSON.parse(students));
}
} catch (error) {
console.log(error);
}
};
const addStudent = () => {
if (studentInput === ''){
Alert.alert('Error', 'Please input student name');
} else {
const newStudent = {
id: Math.random().toString(),
Name: studentInput,
};
setStudent([...student,newStudent]);
setStudentInput('');
}
};
const deleteStudent = (studentId) => {
const newStudent = student.filter(item => item.id !== studentId);
setStudent(newStudent);
};
return (
<View styles={styles.container}>
<TouchableOpacity onPress={()=> navigation.goBack()} style={styles.button}>
<Text>Back</Text>
</TouchableOpacity>
<Text style={{fontWeight: 'bold', fontSize: 20}}>[ Classroom Name ]</Text>
<TextInput
style={styles.input}
placeholder={'Add Student Name'}
value={studentInput}
onChangeText={(text) => setStudentInput(text)}
/>
<TouchableOpacity onPress={()=> addStudent()} style={styles.button}>
<Text>Add Student</Text>
</TouchableOpacity>
<FlatList
style={styles.flatlist}
data={student}
keyExtractor = { (item) => item.id.toString() }
renderItem={({ item }) => (
<View style={styles.listItem}>
<View>
<Text style={[styles.classText , {fontSize: 18}]}>
{item?.Name}
</Text>
</View>
<View >
<TouchableOpacity style={[styles.delete ]} onPress={() => deleteStudent(item?.id)}>
<Icon name="remove" size={15} color={'#fff'} />
</TouchableOpacity>
</View>
</View>
)}
/>
</View>
);
};
export default Classroom;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
},
input: {
width: '70%',
borderBottomWidth: 1,
marginBottom: 20,
},
button: {
backgroundColor: 'lightblue',
padding: 10,
marginBottom: 10,
},
listItem: {
flexDirection: 'row',
justifyContent: 'space-between',
width: '70%',
alignItems: 'center',
},
delete: {
backgroundColor: '#ff3333',
padding: 5,
color: '#fff',
borderWidth: 1,
borderColor: '#ff9999',
borderRadius: 5,
},
});
You are using the same AsyncStorage key 'student' regardless of which classroom you are looking at. You need to keep your student lists separate, so you'll need a separate key for each. Something like:
const key = `students_in_room_${classroomId}`
You can get the classroom id (A, B, C) through the route prop from your navigation.
Edit: You would use this unique key instead of the string 'students' for reading and writing to AsyncStorage. That way you can have separate stored values for each classroom.
const students = await AsyncStorage.getItem(key);
await AsyncStorage.setItem(key, stringifyStudent);
i've done the react-native-pdf to show the slides of my pdf file. But, I want to set the current page state to show up on the display. And when the value is set, it'll refresh that screen and goes back to the first page automatically.
this is my code:
import React, { useState } from 'react';
import { StyleSheet, Dimensions, View, Text } from 'react-native';
import Pdf from 'react-native-pdf';
function Work() {
const [currentPage, setCurrentPage] = useState()
const ShowPdf = () => {
const source = { uri: 'http://samples.leanpub.com/thereactnativebook-sample.pdf', cache: true };
return (
<Pdf
source={source}
onLoadComplete={(numberOfPages, filePath) => {
console.log(`number of pages: ${numberOfPages}`);
}}
onPageChanged={(page, numberOfPages) => {
console.log(`current page: ${page}`);
setCurrentPage(page) //set the cuurentPage
}}
onError={(error) => {
console.log(error);
}}
onPressLink={(uri) => {
console.log(`Link presse: ${uri}`)
}}
style={styles.pdf} />
)
}
return (
<View style={styles.container}>
<ShowPdf />
<View style={styles.pageNumber}>
<Text>{currentPage}</Text>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
//marginTop: 25,
//backgroundColor: 'red',
backfaceVisibility: 'hidden'
},
pdf: {
flex: 1,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
pageNumber: {
position: 'absolute',
left: 20,
top: 20,
backgroundColor: 'rgba(173, 173, 173, 0.5)',
padding: 13,
borderRadius: 6,
}
});
export default Work;
my emulator display:
image
Anyway I can fix this?
Instead of use this
<View style={styles.container}>
<ShowPdf />
<View style={styles.pageNumber}>
<Text>{currentPage}</Text>
</View>
</View>
please use it
<View style={styles.container}>
<Pdf
source={{ uri: path }}
onLoadComplete={(numberOfPages, filePath) => {
console.log(`number of pages: ${numberOfPages}`);
}}
onPageChanged={(page, numberOfPages) => {
console.log(`current page: ${page}`);
setCurrentPage(page) //set the cuurentPage
}}
onError={(error) => {
console.log(error);
}}
onPressLink={(uri) => {
console.log(`Link presse: ${uri}`)
}}
style={styles.pdf} />
<View style={styles.pageNumber}>
<Text>{currentPage}</Text>
</View>
</View>
<ShowPdf/> is your custom react component it will be re-rendered for every page change. So, that is why you faced this problem
I'm new to React Native, and I'm following along with an online tutorial.
This is my App.js file:
import React, { useState, useEffect } from 'react';
import {View,Text,ImageBackground,FlatList, Image, TouchableHighlight } from 'react-native';
import bookmarkIcon from './assets/bookmark.png';
import readIcon from './assets/read.png';
import styles from './styles';
const ArticleItem = ({article}) => {
const { title, description, url, urlToImage } = article;
return (
<View style = { styles.articleContainer }>
<Image style={ styles.articleImage } source={{ uri: urlToImage }} />
<Text style= { styles.articleTitle }>
{ title }
</Text>
<Text style = { styles.articleDescription }>
{ description }
</Text>
<View style = { styles.articleBtns}>
<IconButton width= "50%" color = "white" bgcolor = "#ff5c5c" icon = { readIcon } onPress = { () => { console.log("Button pressed!")} } title = "Open" />
<IconButton width= "50%" color = "white" bgcolor = "#ff5c5c" icon = { bookmarkIcon } onPress = { () => { console.log("Button pressed!")} } title = "Read later" />
</View>
</View>
)
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: 1,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
FlatListHeader = () => {
return (
<View elevation={1}
style={{
height: 100,
width: "97%",
margin: 5,
backgroundColor: "#fff",
border: 2.9,
borderColor: "black",
alignSelf: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 16,
},
shadowOpacity: 1,
shadowRadius: 7.49
}}
>
<Text style={{
textShadowColor: 'black',
textShadowOffset: { width: 1, height: 3 },
textShadowRadius: 10,
fontSize: 40,
fontWeight: '800',
flex: 1,
alignSelf: "center",
paddingTop: 30
}}
>Latest articles</Text>
</View>
);
}
const IconButton = ({title, color, bgcolor, onPress, width, icon }) =>{
return (
<TouchableHighlight onPress = { onPress } style= { { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', backgroundColor: bgcolor } }>
<View style={ {width: width, flexDirection: 'row', justifyContent: 'center', alignItems: 'center' } }>
<Image style = { { height: 27, width:27, margin : 5 } } source = { icon }></Image>
<Text style = { {color: color }} > { title } </Text>
</View>
</TouchableHighlight>
);
}
const HomeScreen = (props) => {
console.log("articles: ", props.articles);
return (
<View>
<FlatList
data={ props.articles }
ListHeaderComponent = { this.FlatListHeader }
ItemSeparatorComponent = { this.FlatListItemSeparator}
keyExtractor={(item, index) => index.toString()}
renderItem={({item}) => <ArticleItem article = { item } />}
/>
</View>
);
}
const SplashScreen = (props) => {
return (
<View style = { styles.container } >
<ImageBackground style= { styles.backgroundImage } source={{uri: 'http://i.imgur.com/IGlBYaC.jpg'}} >
<View style= { styles.logoContainer }>
<Text style = { styles.logoText }>
Newzzz
</Text>
<Text style = { styles.logoDescription }>
Get your doze of daily news!
</Text>
</View>
</ImageBackground>
</View>
);
}
const App = () => {
const URL = 'https://raw.githubusercontent.com/nimramubashir/React-Native/fetch/articles.json';
const [articles, setArticles] = useState([]);
const [loading, setLoading ] = useState(true);
useEffect(()=>{
fetch(URL)
.then((response) => response.json())
.then((responseJson) => {
return responseJson.articles;
})
.then( articles => {
setArticles(articles);
console.log(articles);
setLoading(false);
})
.catch( error => {
console.error(error);
});
} , []);
if (loading){
return <SplashScreen />
} else {
return <HomeScreen articles = { articles }/>
}
};
export default App
The code is the same as the tutorial, but when I'm trying to run this code, I'm getting an Error
ReferenceError: FlatListItemSeparator is not defined
I've tried to import the FlatListItemSeparator, but since it is read-only, I can't. I'm getting this error at both FlatListItemSeparator and FlatListHeader. Why am I getting this error, and how can I solve it?
you are having each component as separate Function-Component. The tutorial is probably based on Class-Components. In Function-Components there is no this, so just remove the this.
I didn't find any soulotion to do animated with FlatList,
I want to hide my Header when I scroll down like In Facebook app.
I tried To use FlatList with diffClamp() without success,
I don't know if I can do it with FlatList but I need also LazyLoading,
Someone Can help me?
This is my Header:
import React, { useState } from "react";
import {
View,
Animated,
Text,
Dimensions,
TouchableOpacity
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { Ionicons } from "#expo/vector-icons";
const Header = props => {
const params = props.scene.route.params;
const [headerHeight] = useState(
params !== undefined && params.changingHeight !== undefined
? params.changingHeight
: Dimensions.get("window").height * 0.065
);
return (
<SafeAreaView style={{ backgroundColor: "rgb(152,53,349)" }}>
<Animated.View
style={{
width: Dimensions.get("window").width,
height: headerHeight,
flexDirection: "row",
backgroundColor: "rgb(152,53,349)"
}}
>
<TouchableOpacity
onPress={() => {
props.navigation.openDrawer();
}}
>
<View
style={{
paddingVertical: "15%",
justifyContent: "center",
paddingHorizontal: 25
}}
>
<Ionicons name="ios-menu" size={30} color={"white"} />
</View>
</TouchableOpacity>
<View style={{ justifyContent: "center", marginLeft: "23%" }}>
<Text
style={{
fontSize: 20,
fontWeight: "bold",
textAlign: "center",
color: "white"
}}
>
MyGameenter code here{" "}
</Text>
</View>
</Animated.View>
</SafeAreaView>
);
};
export default Header;
This is my FlatLIst:
import React from "react";
import { View, FlatList, StyleSheet } from "react-native";
import { EVENTS } from "../data/dummy-data";
import Event from "./Event";
const renderGridItem = itemData => {
return <Event item={itemData.item} />;
};
const ShowEvents = props => {
return (
<View style={styles.list}>
<FlatList
keyExtractor={(item, index) => item.id}
data={EVENTS}
renderItem={renderGridItem}
numColumns={1}
/>
</View>
);
};
const styles = StyleSheet.create({
list: {
flex: 1,
justifyContent: "center",
alignItems: "center"
}
});
export default ShowEvents;
Use
onScroll={(e) => console.log(e.nativeEvent.contentOffset.y)}
Working Example: https://snack.expo.io/#msbot01/privileged-candies
import React, { Component } from 'react';
import { Text, View, StyleSheet, ScrollView, FlatList } from 'react-native';
import Constants from 'expo-constants';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
DATA: [],
previous: 0,
hide: false,
};
}
componentDidMount() {
var array = [];
for (var i = 0; i < 100; i++) {
var a = { id: i, value: i };
array.push(a);
}
this.setData(array);
}
setData(a) {
this.setState({
DATA: a,
});
}
Item({ title }) {
return (
<View
style={{
width: '100%',
height: 30,
marginTop: 5,
backgroundColor: 'green',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text />
</View>
);
}
_onScroll(event) {
// console.log('>>>>>>>>>>>'+this.state.data);
if (this.state.previous < event) {
this.setState({
hide: true,
previous: event,
});
} else {
this.setState({
hide: false,
previous: event,
});
}
console.log(event);
}
render() {
return (
<View style={{ flex: 1 }}>
{this.state.hide == true ? null : (
<View
style={{
width: '100%',
height: 50,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text>Hide me while scrolling</Text>
</View>
)}
<FlatList
onScroll={e => this._onScroll(e.nativeEvent.contentOffset.y)}
data={this.state.DATA}
renderItem={({ item }) => (
<View
style={{
width: '100%',
height: 30,
marginTop: 5,
backgroundColor: 'green',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text />
</View>
)}
keyExtractor={item => item.id}
/>
</View>
);
}
}
const styles = StyleSheet.create({});
import React, { useState } from "react";
import { View, FlatList, StyleSheet, Platform, Dimensions } from "react-native";
import { EVENTS } from "../data/dummy-data";
import Event from "./Event";
const HeaderHeight = () => {
if (Platform.OS === "android" && Dimensions.get("window").height < 600)
return Dimensions.get("window").height * 0.075 + 20;
else if (Platform.OS === "android")
return Dimensions.get("window").height * 0.058 + 20;
else return Dimensions.get("window").height * 0.01 + 20;
};
const renderGridItem = itemData => {
return <Event item={itemData.item} />;
};
const ShowEvents = props => {
const [previous, SetPrevious] = useState(false);
const [hide, SetHide] = useState(false);
_onScroll = event => {
const headerHeight = HeaderHeight();
if (event > headerHeight) {
SetHide(true);
props.navigation.setParams({
hide: true
});
SetPrevious(event);
} else if (event < 0.1) {
SetHide(false);
props.navigation.setParams({
hide: false
});
SetPrevious(event);
}
};
return (
<View style={styles.list}>
<FlatList
onScroll={e => _onScroll(e.nativeEvent.contentOffset.y)}
keyExtractor={(item, index) => item.id}
data={EVENTS}
renderItem={renderGridItem}
numColumns={1}
/>
</View>
);
};
const styles = StyleSheet.create({
list: {
flex: 1,
justifyContent: "center",
alignItems: "center"
}
});
export default ShowEvents;