React Native reload flatlist each time user hits the API - react-native

React, {useCallback, useState, useEffect, useRef} from 'react';
import {
View,
SafeAreaView,
FlatList,
Image,
Text,
TextInput,
TouchableOpacity,
StyleSheet,
ActivityIndicator,
} from 'react-native';
import Nodata from '../main/banking/common/Nodata';
import Icon from 'react-native-vector-icons/Ionicons';
import Toast from 'react-native-simple-toast';
import axios from 'axios';
import useSessionToken from '../hooks/useSessionToken';
import moment from 'moment';
import ListData from '../main/banking/common/ListData';
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
import ShimmerPlaceholder from 'react-native-shimmer-placeholder';
import LinearGradient from 'react-native-linear-gradient';
function CustomerNotes(props) {
const session = useSessionToken();
const textInputRef = useRef();
const [notes, setNotes] = useState('');
const [data, setData] = useState({
notesList: [],
visible: false,
});
useEffect(() => {
getNotes();
}, [session,data]);
const getNotes = async () => {
try {
const qs = require('qs');
let params = qs.stringify({
cust_id: props.customerId,
operation: 'notes_list',
});
await axios
.post(
'https://abc.cdhgfhg.com/adghagsa',
params,
{
headers: {
Cookie: session?.token,
'Content-Type': 'application/x-www-form-urlencoded',
},
},
)
.then(function (response) {
if (response.data.status === 1) {
console.log('customernotes', response.data.data.hits.hits);
setData({
...data,
notesList: response.data.data.hits.hits,
visible: false,
});
}
})
.catch(function (error) {
console.log('CustomerNoteserror', error);
});
} catch (error) {
console.log('CustomerNoteserror', error);
}
};
const renderItem = ({item, index}) => {
var initialtv = Number(index + 1).toString();
var formattedDate = moment(item._source.added_on).format(
'ddd, MMM DD YYYY',
);
// console.log('initial', item, initialtv);
const data = {
text: item._source.notes,
mobile: formattedDate,
amount: '',
};
return <ListData item={data} />;
};
const handleInputSubmit = useCallback(ev => {
const input = ev.nativeEvent.text;
// validate all you want here
setNotes(input);
}, []);
const submitNotes = () => {
if (notes.length > 0) {
setData(prevState => ({
...prevState,
visible: true,
}));
addNotes();
} else {
Toast.show('Enter Notes');
}
};
const addNotes = async () => {
try {
const qs = require('qs');
let params = qs.stringify({
cust_id: props.customerId,
operation: 'add_notes',
notes: notes,
});
await axios
.post(
'https://abc.cdhgfhg.com/adghagsa',
params,
{
headers: {
Cookie: session?.token,
'Content-Type': 'application/x-www-form-urlencoded',
},
},
)
.then(function (response) {
if (response.data.status === 1) {
// console.log('addNotes', response.data);
getNotes();
}
})
.catch(function (error) {
console.log('addNoteserror', error);
});
} catch (error) {
console.log('CustomerNoteserror', error);
}
};
return (
<View style={{flex: 1, backgroundColor: 'white'}}>
{data.visible == true ? (
<ActivityIndicator
size="large"
color="#0096FF"
style={{
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
}}
/>
) : null}
{data.notesList.length != 0 ? (
<FlatList
data={data.notesList}
renderItem={renderItem}
style={{marginTop: hp('1.5%')}}
/>
) : (
<Nodata />
)}
<View
style={{
flex: 1,
flexDirection: 'row',
position: 'absolute',
bottom: 0,
marginBottom: '4%',
}}>
<TextInput
ref={textInputRef}
autoFocus={false}
style={styles.TextInputStyleClass}
placeholder="Write something"
placeholderTextColor={'#D0D0D0'}
onChangeText={
text => setNotes(text)
// (data.notes = text)
}
/>
<TouchableOpacity
onPress={() => submitNotes()}
style={{
height: 44,
width: 46,
backgroundColor: '#0096FF',
borderRadius: 6,
justifyContent: 'center',
alignItems: 'center',
elevation: 5,
marginRight: '4%',
}}>
<Icon
name={'send'}
size={20}
color="#ffffff"
style={{alignItems: 'center', justifyContent: 'center'}}
/>
</TouchableOpacity>
</View>
</View>
);
}
export default React.memo(CustomerNotes);
const styles = StyleSheet.create({
TextInputStyleClass: {
height: 45,
borderColor: '#0096FF',
flex: 7,
marginLeft: '4%',
marginRight: '4%',
flex: 1,
borderRadius: 6,
borderWidth: 1,
paddingLeft: 12,
fontFamily: 'Poppins-Medium',
fontSize: 14,
backgroundColor: 'white',
},
titleStyle: {
fontSize: 13,
color: '#000000',
fontFamily: 'Poppins-SemiBold',
},
subTitle: {
fontSize: 11,
fontFamily: 'Poppins',
color: '#000000',
},
});
I am fetching data from getNotes() API to render in Flatlist also I have a textinput at the bottom of the page. Whenever I submit textinput data to addNotes API data is added sucessfully and again I am calling getNotes API to reload the data in flatlist.
The issue is data rendering in flatlist is getting very slow and also the activityIndicator is not loading properly. When I call submitNotes the activityIndicator should start loading once the data is added and finished data rendering in flatlist the activityloader should stop loading.

To reload the flatlist each time the data changes you can pass extraData props. For performance optimizations, you can limit the number of items to be loaded at once using initialNumToRender, and onScroll more items will be loaded. Toggle refreshing props to true/false based on API response.
<FlatList
data={data.notesList}
renderItem={renderItem}
style={{marginTop: hp('1.5%')}}
keyExtractor={...}
extraData={data.noteList}
initialNumToRender={10}
refreshing={true}
/>

Related

How to remove submitted text input on React Native?

My code is working fine, it's pushing all the data to firebase as it should. I'm having no problems at all.
I just want to implement to remove the submitted data in text input. Since it stays there and you have to remove it manually.
I've been trying to add another function to 'onPress' to clear the inputs, but I can't seem to make it work. Any advice or help will be more than welcome.
Please check my code here below.
import { useState } from 'react';
import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native';
import { addDoc, collection, doc, setDoc } from "firebase/firestore";
import { db } from './components/config';
export default function App() {
const [nombre, setNombre] = useState('');
const [cantidad, setCantidad] = useState('');
const [pretexto, setPretexto] = useState('');
function create(){
//Submit data
addDoc(collection(db, "users"), {
nombre: nombre,
cantidad: cantidad,
pretexto: pretexto
}).then(() => {
console.log('Data submitted');
}).catch((error) => {
console.log(error);
})
}
return (
<View style={styles.container}>
<View style={styles.textBox}>
<TextInput value ={nombre} onChangeText={(nombre) => {setNombre(nombre)}} placeholder='Nombre del caretubo' style={styles.inputOne}></TextInput>
<TextInput value={cantidad} onChangeText={(cantidad) => {setCantidad(cantidad)}} placeholder='Cantidad que debe el HP' style={styles.inputTwo}></TextInput>
<TextInput value={pretexto} onChangeText={(pretexto) => {setPretexto(pretexto)}} placeholder='Pretexto' style={styles.inputThree}></TextInput>
<TouchableOpacity style={styles.botonaso} onPress={() => {create; setNombre(''); }}>
<Text style={styles.botonasoTexto}>Subir</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
textBox: {
width: '100%',
padding: 12,
borderColor: 'gray',
borderWidth: 1,
borderRadius: 20,
},
inputOne: {
fontSize: 15,
},
inputTwo: {
fontSize: 15,
},
inputThree: {
fontSize: 15
},
botonaso: {
backgroundColor: '#202A44',
alignItems: 'center',
borderRadius: 20,
padding: 10
},
botonasoTexto: {
color: 'white'
}
});
const clearTextInputs = () => {
setNombre('');
setCantidad('');
setPretexto('');
};
function create() {
//Submit data
addDoc(collection(db, "users"), {
nombre: nombre,
cantidad: cantidad,
pretexto: pretexto
}).then(() => {
console.log('Data submitted');
clearTextInputs(); // <---------- add here
}).catch((error) => {
console.log(error);
})
}
<TouchableOpacity style={styles.botonaso} onPress={create}> // <----- onPress here
<Text style={styles.botonasoTexto}>Subir</Text>
</TouchableOpacity>

expo ImageManipulator returning [TypeError: undefined is not an object (evaluating '_expo.ImageManipulator.manipulate')]

for some reason
const manipResult = await ImageManipulator.manipulate(
image,
[{ resize: { width: 640, height: 480 } }],
{ format: 'jpg' }
);
returns [TypeError: undefined is not an object (evaluating '_expo.ImageManipulator.manipulate')]
which is weird because it worked one time and then this started to be returned by react native whenever it runs this line of code. so basically what im trying to do is resize the image and then send it to an api but for some reason it won't work and keeps giving this error even though data.uri isn't undefined
whole code
import React, { useState, useEffect, useRef } from 'react';
import { Text, View, StyleSheet, TouchableOpacity, Image } from 'react-native';
import Constants from 'expo-constants';
import { Camera, CameraType } from 'expo-camera';
import * as MediaLibrary from 'expo-media-library';
import { MaterialIcons } from '#expo/vector-icons';
import Button from './src/components/Button';
import axios from 'axios'
import { Buffer } from "buffer";
import * as FS from "expo-file-system";
import { ImageManipulator } from 'expo';
export default function App() {
const [hasCameraPermission, setHasCameraPermission] = useState(null);
const [image, setImage] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const [flash, setFlash] = useState(Camera.Constants.FlashMode.off);
const cameraRef = useRef(null);
useEffect(() => {
(async () => {
MediaLibrary.requestPermissionsAsync();
const cameraStatus = await Camera.requestCameraPermissionsAsync();
setHasCameraPermission(cameraStatus.status === 'granted');
})();
}, []);
const takePicture = async () => {
if (cameraRef) {
try {
const data = await cameraRef.current.takePictureAsync();
console.log(data);
const manipResult = await ImageManipulator.manipulate(
data.uri,
[{ resize: { width: 640, height: 480 } }],
{ format: 'jpg' }
);
setImage(manipResult0);
} catch (error) {
console.log(error);
}
}
};
uriToBase64 = async (uri) => {
let base64 = await FS.readAsStringAsync(uri, {
encoding: FS.EncodingType.Base64,
});
return base64;
};
toServer = async (mediaFile) => {
const url = "api url";
let response = await FS.uploadAsync(url, mediaFile.uri, {
headers: {
"content-type": "image/jpeg",
},
httpMethod: "POST",
uploadType: FS.FileSystemUploadType.BINARY_CONTENT,
});
console.log(response);
};
const savePicture = async () => {
if(image) {
try {
const asset= await MediaLibrary.createAssetAsync(image);
await toServer({
type:"image",
base64: uriToBase64(image),
uri: image,
});
setImage(null);
console.log('saved successfully');
} catch (error) {
console.log(error);
}
}
};
if (hasCameraPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
{!image ? (
<Camera
style={styles.camera}
type={type}
ref={cameraRef}
flashMode={flash}
>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: 30,
}}
>
<Button
title=""
icon="retweet"
onPress={() => {
setType(
type === CameraType.back ? CameraType.front : CameraType.back
);
}}
/>
<Button
onPress={() =>
setFlash(
flash === Camera.Constants.FlashMode.off
? Camera.Constants.FlashMode.on
: Camera.Constants.FlashMode.off
)
}
icon="flash"
color={flash === Camera.Constants.FlashMode.off ? 'gray' : '#fff'}
/>
</View>
</Camera>
) : (
<Image source={{ uri: image }} style={styles.camera} />
)}
<View style={styles.controls}>
{image ? (
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: 50,
}}
>
<Button
title="Re-take"
onPress={() => setImage(null)}
icon="retweet"
/>
<Button title="Save" onPress={savePicture} icon="check" />
</View>
) : (
<Button title="Take a picture" onPress={takePicture} icon="camera" />
)}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#000',
padding: 8,
},
controls: {
flex: 0.5,
},
button: {
height: 40,
borderRadius: 6,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
text: {
fontWeight: 'bold',
fontSize: 16,
color: '#E9730F',
marginLeft: 10,
},
camera: {
flex: 5,
borderRadius: 20,
},
topControls: {
flex: 1,
},
});

How to get all the pdf files available in internal storage of android in react native

I am using react-native-fs for reading files in device's external storage. I want to get all pdf books stored in an android device and list them in the screen. Searched in google, read docs in react-native-fs but not succeed getting all pdf books. please help if something wrong with my code.
What I'm doing wrong?
Here is my code.
import React, { useState, useEffect } from 'react';
import {
Alert,
StyleSheet,
Text,
View,
Dimensions,
ImageBackground,
ScrollView,
PermissionsAndroid,
ActivityIndicator,
} from 'react-native';
import RNFS from 'react-native-fs';
import BookOffline from '../components/BookOffline';
const MyBooks = ({ navigation }) => {
// collecting data from device
const [books, setBooks] = useState([])
const [bookList, setBookList] = useState([]);
useEffect(() => {
getPermission();
}, []);
const getPermission = async () => {
try {
PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE
).then(granted => {
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
readStorage();
} else {
//If permission denied then show alert
Alert.alert('Not Granted storage_permission');
navigation.goBack();
}
});
} catch (err) {
//To handle permission related issue
console.log('error', err);
}
};
const readStorage = async () => {
let list2 = [];
await RNFS.readDir(RNFS.ExternalStorageDirectoryPath) // On Android, use "RNFS.DocumentDirectoryPath" (MainBundlePath is not defined)
.then(result => {
result.forEach((item, index) => {
// console.log(index, item)
if (item.name.endsWith('.pdf')) {
setBooks([...books, item])
}
else if (item.isDirectory()) {
RNFS.readDir(item.path)
.then(result => {
list2 = result.filter((item) => item.name.endsWith('.pdf'))
setBooks([...books, ...list2])
}).catch((error) => {
console.log(error)
})
}
});
setBookList(books)
console.log("bookList", bookList)
})
.catch(error => {
console.log(error);
});
};
return bookList.length == 0 ? (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Loading...</Text>
<ActivityIndicator size="large" />
</View>
) : (
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<ImageBackground
source={require('../assets/images/tech-dark-design.jpg')}
resizeMode="cover"
style={{ width: '100%' }}>
<ScrollView style={styles.images}>
{bookList.map((item, index) => {
return <BookOffline data={item} key={index} />;
})}
</ScrollView>
</ImageBackground>
</View>
);
};
export default MyBooks;
const styles = StyleSheet.create({
container: {
height: Dimensions.get('window').height - 110,
// padding: 5,
},
list: {
width: '100%',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.2,
shadowRadius: 1.41,
elevation: 2,
marginBottom: 1,
},
});

Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'camera.takePictureAsync') React-Native expo-camera

I am trying to create a function that will access my device's camera, and will allow me to take a picture, but I get the above error. I modeled this similar to requesting access to the camera roll and it works fine, but I cannot get it to work for the camera.
What may be causing this? Below is some of my code:
import * as ImagePicker from 'expo-image-picker' //I am using expo
import {Camera} from 'expo-camera'
export default function Photo(){
// Image Picker function start
useEffect(() => {
(async ()=> {
if (Platform.OS != 'web'){
const ( status !== 'granted') {
if(status !== 'granted) {
alert('Camera roll required to upload photo from your library');
}
}
})();
},[]);
//Image Picker function end
const camera = useRef(null) //added this
const takePicture = async () => { // added this
useEffect(() => {
(async () => {
if (Platform.OS !== 'web'){
const { status1 } = await Camera.requestPermissionsAsync();
if (status1 !== 'granted'){
alert('Camera required to take a photo');
}
} //added this
},
})();
}, [])
}
<Camera //added this
ref = { camera }
onGoogleVisionBarcodesDetected = {({barcodes}) => {
console.log(barcodes)
}}
/> //added this
<View style = {[ styles.button, {justifyContent: 'center', borderRadius: 20, backgroundColor: '#fff', paddingTop: 10, width: width*0.5, alignItems: 'center' } ]}>
<TouchableOpacity
color='#fff'
onPress = { ()=> takePicture () }
>
<Text style = {[ styles.button, {}]}>Take Photo </Text>
</TouchableOpacity>
</View>
This might help
import React, { useRef } from 'react'
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'
import { RNCamera } from 'react-native-camera'
function PlayWithCamera() {
const camera = useRef(null);
const takePicture = async () => {
const result1 = await camera.takePictureAsync();
....
};
return (
<View style={styles.container}>
<RNCamera
ref={camera}
.....
onGoogleVisionBarcodesDetected={({ barcodes }) => {
console.log(barcodes)
}}
/>
<View ... >
<TouchableOpacity
onPress={() => takePicture() } // change here
>
......
</TouchableOpacity>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: 'black',
},
preview: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
},
capture: {
flex: 0,
backgroundColor: '#fff',
borderRadius: 5,
padding: 15,
paddingHorizontal: 20,
alignSelf: 'center',
margin: 20,
},
})
export default PlayWithCamera

How to use props in function which has navigation component

I'm trying to use props in function component. But the the function has navigation component in it like below.
const AddProductList = ({props, route, navigation}) => {
const {navData} = route.params;
var [data, setData] = useState(DATA);
...
...
...
}
because of route, navigation I think props is undefined.
I'm trying to write this example purely in functional style.
I need to do some thing like reading current data from flat list on tap.
var id = props.item.product_id_to_delete
because props is undefined I'm not getting item id to delete the tapped item.
Kindly anyone help me.
check full code
import React, {useState} from 'react';
import {View} from 'react-native-animatable';
import {
TextInput,
TouchableOpacity,
FlatList,
} from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/FontAwesome';
import {StyleSheet, Pressable, Text, Button} from 'react-native';
import * as Animatable from 'react-native-animatable';
import Swipeout from 'react-native-swipeout';
import ButtonPressable from '../../components/ButtonPressable';
var sqlite_wrapper = require('./sqliteWrapper');
const DATA = [
{
prodName: 'Added data will look like this',
},
];
const AddProductList = ({item, route, navigation}) => {
const {navData} = route.params;
const [prodName, setProdName] = useState('');
var [data, setData] = useState(DATA);
const swipeSettings = {
style: {
marginBottom: 10,
},
autoClose: false,
backgroundColor: 'transparent',
close: false,
disabled: false,
onClose: (sectionID, rowId, direction) => {
console.log('---onclose--');
},
onOpen: (sectionID, rowId, direction) => {
console.log('---onopen--' + item);
},
right: [
{
backgroundColor: 'dodgerblue',
color: 'white',
text: 'Edit',
onPress: () => {
console.log('-----edit-----');
},
},
],
left: [
{
backgroundColor: 'red',
color: 'white',
text: 'Delete',
onPress: () => {
console.log('-----delete-----');
sqlite_wrapper.deleteById;
},
type: 'delete',
// component : (<ButtonPressable text="delete" />)
},
],
// buttonWidth: 100,
};
return (
<View style={styles.container}>
<Animatable.View
animation="bounceIn"
duration={1000}
style={styles.inputFieldView}>
<TextInput
style={styles.textInput}
onChangeText={(value) => setProdName(value)}
placeholder="Add the Product"
defaultValue={prodName}
/>
<TouchableOpacity
style={styles.addView}
onPress={() => {
sqlite_wrapper
.insert({prodName: prodName}, sqlite_wrapper.collection_product)
.then((result) => {
console.log('---result---');
console.log(result);
if (result.rowsAffected) {
fetchAllData();
}
});
function fetchAllData() {
sqlite_wrapper
.readAll(sqlite_wrapper.collection_product)
.then((resultData) => {
console.log('---resultData---');
console.log(resultData);
setData(resultData);
setProdName('');
});
}
// without sql this is how to update the state having a array
// const updatedArray = [...data];
// updatedArray.push({prodName: prodName});
// setData(updatedArray);
// setProdName('');
}}>
<Icon name="plus" size={16} style={styles.add} color="white" />
</TouchableOpacity>
</Animatable.View>
<Animatable.View
animation="bounceInLeft"
duration={1500}
style={{flex: 1}}>
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={({item, index}) => (
<Swipeout {...swipeSettings}>
<View style={styles.listView}>
<Text style={styles.listViewText}>{item.prodName}</Text>
</View>
</Swipeout>
)}
/>
</Animatable.View>
</View>
);
};
var styles = StyleSheet.create({
container: {
flex: 1,
},
inputFieldView: {
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch',
margin: 10,
},
textInput: {
flex: 1,
backgroundColor: '#b2ebf2',
borderTopLeftRadius: 7,
borderBottomLeftRadius: 7,
fontSize: 16,
},
addView: {
backgroundColor: '#0f4c75',
alignSelf: 'stretch',
alignItems: 'center',
justifyContent: 'center',
borderTopEndRadius: 7,
borderBottomEndRadius: 7,
padding: 9,
},
add: {
padding: 7,
},
listView: {
padding: 20,
backgroundColor: 'green',
margin: 0,
borderRadius: 0,
},
listViewText: {
color: 'white',
},
});
export default AddProductList;
change your component to this...
const AddProductList = ({item, route, navigation}) => {
const {navData} = route.params;
var [data, setData] = useState(DATA);
var id = item.product_id_to_delete
...
}
explanation: you are already doing object destruction, so props is all total i.e main parent, but navigation, route is the elements that
like:
props: {
navigation,
route,
...
}