How to do Refresh in React Native ScrollView with refreshControl? - react-native

Now I would like to pull down a scrollView and refresh this component, so I have followed the official document mentioning onRefresh and RefreshContorol from react-native.
However, I don't know why my code is not working and get error...
The code below is my code.
<View style={styles.container}>
<ScrollView
contentContainerStyle={{ flexDirection: 'row', flexWrap: 'wrap' }}
refreshControl={<RefreshControl refreshing={this.state.refreshing} onRefresh={this.setState({ refreshing: true })} />}
>
{this.renderItemBox()}
</ScrollView>
</View>

Below is the sample code in which you can find RefreshController integration with ScrollView:
import { ScrollView, RefreshControl } from 'react-native';
class RefreshableList extends Component {
constructor(props) {
super(props);
this.state = {
refreshing: false,
};
}
_onRefresh = () => {
this.setState({refreshing: true});
fetchData().then(() => {
this.setState({refreshing: false});
});
}
render() {
return (
<ScrollView
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
/>
}
/>
);
}
}

on me it worked
import React from 'react';
import {
RefreshControl,
ScrollView,
StyleSheet,
View,
} from 'react-native';
import {WebView} from 'react-native-webview';
const wait = timeout => {
return new Promise(resolve => setTimeout(resolve, timeout));
};
const Main = () => {
const webViewRef = React.useRef();
const [refreshing, setRefreshing] = React.useState(false);
const [enablePTR, setEnablePTR] = React.useState(false);
const onRefresh = React.useCallback(() => {
webViewRef.current.reload();
setRefreshing(true);
wait(2000).then(() => setRefreshing(false));
}, []);
const handleEvent = e => {
if (e.nativeEvent.contentOffset.y > 100) {
setEnablePTR(false);
} else {
setEnablePTR(true);
}
};
return (
<View style={styles.container}>
<ScrollView
scrollEnabled={false}
contentContainerStyle={styles.container}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
enabled={enablePTR}
/>
}
>
<WebView
source={{ uri: "https://example.com/" }}
ref={(ref) => (webViewRef.current = ref)}
javaScriptEnabled={true}
injectedJavaScript="setTimeout(() => {document.addEventListener('scroll', function (event) {window.ReactNativeWebView.postMessage(JSON.stringify(document.getElementsByClassName('topconteiner')[0].scrollTop));},true);}, 300);true;"
onScroll={(event) => handleEvent(event)}
/>
</ScrollView>
</View>
);
};
export default Main;
const styles = StyleSheet.create({
container: {backgroundColor: '#fff', flex: 1},
});

Related

React Native flatlist with checkbox

I am new to react native. I am writing the code in class component, I need a flatlist with checkbox that allow multiple select, add the selected data could be save in a array and pass to other screen. I have no idea about that.. Can anyone help??
Try this example:
import React, { Component } from 'react';
import { View, Text, Image, FlatList, TextInput } from 'react-native';
import { ListItem, Body } from 'native-base';
import CheckBox from '#react-native-community/checkbox';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
serachdata: [],
selectedId: []
};
}
componentDidMount(){
this.ApiCalling();
}
ApiCalling = () => {
const url = "YOUR_API"
fetch(url)
.then(res => res.json())
.then(res => {
this.setState({data: res.data})
this.setState({serachdata: res.data})
})
.catch(error => {
console.log("error ", error)
})
}
onCheckBoxPress = (id) => {
let checkboxes = this.state.selectedId;
if(checkboxes && checkboxes.includes(id)){
checkboxes.splice( checkboxes.indexOf(id), 1 );
} else {
checkboxes = checkboxes.concat(id);
}
this.setState({selectedId:checkboxes})
console.log("selectde checkbox id: ", checkboxes)
}
_filter = (text) => {
const newData = this.state.data.filter(item => {
const itemData = `${item.first_name.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
this.setState({serachdata:newData})
}
render(){
return(
<View style={{ marginTop: 50 }}>
<TextInput
autoCapitalize='none'
autoCorrect={false}
style={{ height: 40, borderColor: 'gray', borderWidth: 1, margin:10 }}
status='info'
placeholder='Search'
onChangeText={(text) => this._filter(text)}
textStyle={{ color: '#000' }}
/>
<FlatList
data={this.state.serachdata}
keyExtractor={(item, index) => String(index)}
renderItem={({item, index}) => {
return(
<ListItem key={index}>
<CheckBox
disabled={false}
value={this.state.selectedId && this.state.selectedId.includes(item.id)}
onChange={()=>this.onCheckBoxPress(item.id)}
/>
<Body>
<View style={{flexDirection:'row', justifyContent:'space-between'}}>
<Image source={{ uri: item.avatar }} style={{ height: 100, width: 100 }} />
<Text>{item.first_name}</Text>
<Text>{item.email}</Text>
{/* <Text>{item.name.last}</Text> */}
</View>
</Body>
</ListItem>)}}
/>
</View>
)
}
};

Why can't I navigate to my Screen using onPress={() => navigation.navigate('SaveProfileImage, { profileImage })}?

I'm developing an app where I have a screen called Add, other called Save, that I navigate between them using onPress={() => navigation.navigate('Save', { image })} inside a button, so I tried to do the same on another screen called profile that should navigate to the screen SaveProfileImage, but when I try this, I get the error TypeError: undefined is not an object (evaluating 'props.route.params') and I can't understand what can be so wrong in my codes:
Here is the Profile codes:
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text, Image, FlatList, Button } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import firebase from 'firebase';
require('firebase/firestore');
import { connect } from 'react-redux';
function Profile({ navigation }, props) {
const [userPosts, setUserPosts] = useState([]);
const [user, setUser] = useState(null);
const [hasGalleryPermission, setHasGalleryPermission] = useState(null);
const [image, setImage] = useState(null);
useEffect(() => {
const { currentUser, posts } = props;
if (props.route.params.uid === firebase.auth().currentUser.uid) {
setUser(currentUser)
setUserPosts(posts)
}
else {
firebase.firestore()
.collection('users')
.doc(props.route.params.uid)
.get()
.then((snapshot) => {
if (snapshot.exists) {
setUser(snapshot.data());
}
else {
console.log('does not exist')
}
})
firebase.firestore()
.collection('posts')
.doc(props.route.params.uid)
.collection('userPosts')
.orderBy('creation', 'desc')
.get()
.then((snapshot) => {
let posts = snapshot.docs.map(doc => {
const data = doc.data();
const id = doc.id;
return { id, ...data }
})
setUserPosts(posts)
});
};
(async () => {
const galleryStatus = await ImagePicker.requestMediaLibraryPermissionsAsync();
setHasGalleryPermission(galleryStatus.status === 'granted');
})();
}, [props.route.params.uid, props.following]);
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
});
if (!result.cancelled) {
setImage(result.uri);
};
};
if (hasGalleryPermission === false) {
return <View />;
};
if (hasGalleryPermission === false) {
return <Text>No access to gallery</Text>;
};
const onLogout = () => {
firebase.auth().signOut();
};
if (user === null) {
return <View />
}
return (
<View style={styles.container}>
{image && <Image source={{ uri: image }}
style={{ flex: 1 }} />}
<Image source={{ uri: props.route.params.profileImage }} />
<View style={styles.containerInfo}>
<Text>{user.name}</Text>
<Text>{user.state}</Text>
<Text>{user.city}</Text>
<Text>{user.email}</Text>
{props.route.params.uid !== firebase.auth().currentUser.uid}
<Button title='Pick Image From Gallery' onPress={() => pickImage()} />
<Button title='Save'
onPress={() => navigation.navigate('SaveProfileImage',
{ profileImage })} />
</View>
<View style={styles.container}>
<FlatList
numColumns={3}
horizontal={false}
data={userPosts}
renderItem={({ item }) => (
<View
style={styles.containerImage}>
<Image
style={styles.image}
source={{ uri: item.downloadURL }}
/>
</View>
)}
/>
</View>
<Button
title='Logout'
onPress={() => onLogout()}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
containerInfo: {
margin: 20
},
containerImage: {
flex: 1 / 3
},
image: {
flex: 1,
aspectRatio: 1 / 1
}
})
const mapStateToProps = (store) => ({
currentUser: store.userState.currentUser,
posts: store.userState.posts,
following: store.userState.following
})
export default connect(mapStateToProps, null)(Profile);
The app.js has a navigation container to control these screens:
<NavigationContainer >
<Stack.Navigator initialRouteName='Main'>
<Stack.Screen name='Main' component={MainScreen} />
<Stack.Screen name='Add' component={AddScreen}
navigation={this.props.navigation}/>
<Stack.Screen name='Save' component={SaveScreen}
navigation={this.props.navigation}/>
<Stack.Screen name='SaveProfileImage' component={SaveProfileImageScreen}
navigation={this.props.navigation}/>
<Stack.Screen name='Comment' component={CommentScreen}
navigation={this.props.navigation}/> </Stack.Navigator>
<NavigationContainer >
I can't understand why I can navigate from the AddScreen to the Save Screen, but I can't do the same between the profileScreen and the SaveProfileImage.
The save is this one:
import React, { useState } from 'react'
import { View, TextInput, Image, Button } from 'react-native'
import firebase from 'firebase'
require('firebase/firestore')
require('firebase/firebase-storage')
export default function Save(props) {
const [caption, setCaption] = useState('')
const uploadImage = async () => {
const uri = props.route.params.image;
const childPath =
`post/${firebase.auth().currentUser.uid}/${Math.random().toString(36)}`;
const response = await fetch(uri);
const blob = await response.blob();
const task = firebase
.storage()
.ref()
.child(childPath)
.put(blob);
const taskProgress = snapshot => {
console.log(`transferred: ${snapshot.bytesTransferred}`)
};
const taskCompleted = () => {
task.snapshot.ref.getDownloadURL().then((snapshot) => {
savePostData(snapshot);
})
};
const taskError = snapshot => {
console.log(snapshot)
};
task.on('state_changed', taskProgress, taskError, taskCompleted);
};
const savePostData = (downloadURL) => {
firebase.firestore()
.collection('posts')
.doc(firebase.auth().currentUser.uid)
.collection('userPosts')
.add({
downloadURL,
caption,
likesCount: 0,
estate: '',
city: '',
creation: firebase.firestore.FieldValue.serverTimestamp()
}).then((function () {
props.navigation.popToTop()
}))
};
return (
<View style={{ flex: 1 }}>
<Image source={{ uri: props.route.params.image }} />
<TextInput
placeholder='Write a Caption . . .'
onChangeText={(caption) => setCaption(caption)}
/>
<Button title='Save' onPress={() => uploadImage()} />
</View>
);
};
The SaveProfileScreen is this other one:
import React, { useState } from 'react'
import { View, TextInput, Image, Button } from 'react-native'
import firebase from 'firebase'
require('firebase/firestore')
require('firebase/firebase-storage')
export default function ProfileImage(props) {
const [caption, setCaption] = useState('')
const uploadImage = async () => {
const uri = props.route.params.image;
const childPath =
`profileImage/${firebase.auth().currentUser.uid}/
${Math.random().toString(36)}`;
console.log(childPath);
const response = await fetch(uri);
const blob = await response.blob();
const task = firebase
.storage()
.ref()
.child(childPath)
.put(blob);
const taskProgress = snapshot => {
console.log(`transferred: ${snapshot.bytesTransferred}`)
};
const taskError = snapshot => {
console.log(snapshot)
};
const taskCompleted = () => {
task.snapshot.ref.getDownloadURL().then((snapshot) => {
savePictureData(snapshot);
})
};
task.on('state_changed', taskProgress, taskError, taskCompleted);
};
return (
<View style={{ flex: 1 }}>
<Image source={{ uri: props.route.params.profileImage }} />
<Button title='Save' onPress={() => uploadImage()} />
</View>
);
};

how to capture image using expo-camera in react native

I am new to react-native. I have created an app. but now I want to Capture Image from this app. I have got the code from expo website But the problem is This code only open camera. I want to capture An Image Through That camera. So if it is possible please help me..
here is my code
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { Camera } from 'expo-camera';
import { Ionicons } from '#expo/vector-icons';
export default function App({navigation}) {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
useEffect(() => {
(async () => {
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
<View style={styles.header}>
<Ionicons style={{paddingLeft:20}} name="arrow-back" size={40}
color="black" onPress={() => navigation.navigate("OtherInfo")} />
<Text style={{fontSize:20, paddingLeft: 70, paddingTop: 10}}>Get Image</Text>
</View>
<Camera style={styles.camera} type={type}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.button}
onPress={() => {
setType(
type === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back
);
}}>
<Text style={styles.text}> Flip </Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
const styles = StyleSheet.create({
camera:{
height:500
},
header:{
flexDirection: 'row'
}
});
Here is the working Example of the small app which takes the picture from Camera as well as Gallary and shows it to after it is clicked or selected
Working App: Expo Snack
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, Button, Image } from 'react-native';
import { Camera } from 'expo-camera';
import * as ImagePicker from 'expo-image-picker';
export default function Add({ navigation }) {
const [cameraPermission, setCameraPermission] = useState(null);
const [galleryPermission, setGalleryPermission] = useState(null);
const [camera, setCamera] = useState(null);
const [imageUri, setImageUri] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const permisionFunction = async () => {
// here is how you can get the camera permission
const cameraPermission = await Camera.requestCameraPermissionsAsync();
setCameraPermission(cameraPermission.status === 'granted');
const imagePermission = await ImagePicker.getMediaLibraryPermissionsAsync();
console.log(imagePermission.status);
setGalleryPermission(imagePermission.status === 'granted');
if (
imagePermission.status !== 'granted' &&
cameraPermission.status !== 'granted'
) {
alert('Permission for media access needed.');
}
};
useEffect(() => {
permisionFunction();
}, []);
const takePicture = async () => {
if (camera) {
const data = await camera.takePictureAsync(null);
console.log(data.uri);
setImageUri(data.uri);
}
};
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
presentationStyle: 0
});
console.log(result);
if (!result.canceled) {
setImageUri(result.assets[0].uri);
}
};
return (
<View style={styles.container}>
<View style={styles.cameraContainer}>
<Camera
ref={(ref) => setCamera(ref)}
style={styles.fixedRatio}
type={type}
ratio={'1:1'}
/>
</View>
<Button title={'Take Picture'} onPress={takePicture} />
<Button title={'Gallery'} onPress={pickImage} />
{imageUri && <Image source={{ uri: imageUri }} style={{ flex: 1 }} />}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
cameraContainer: {
flex: 1,
flexDirection: 'row',
},
fixedRatio: {
flex: 1,
aspectRatio: 1,
},
button: {
flex: 0.1,
padding: 10,
alignSelf: 'flex-end',
alignItems: 'center',
},
});

How to give permission to access camera photo library in visual studio code for a ReactNative Iphone App

I want to know how to give permission to access camera photo library in visual studio code for a ReactNative Iphone App?
Here is my code:
FeedBackScreen.js:
import React,{Component} from 'react';
import {View,Text, StyleSheet,FlatList,Dimensions,TouchableOpacity,Image} from 'react-
native';
import {ActionSheet,configuration,onSelect,Root,options} from 'native-base';
import ImagePicker from 'react-native-image-crop-picker';
const width = Dimensions.get('window').width;
export default class FeedBackScreen extends Component{
constructor(props){
super(props);
this.state = {
fileList:[]
}
}
onSelectedImage = (image) =>{
let newDataImg = this.state.fileList;
const source = {uri:image.path};
let item = {
id:Date.now(),
url:source,
content:image.content
}
newDataImg.push(item);
this.setState({fileList:newDataImg})
};
takePhotoFromCamera = () =>{
ImagePicker.openPicker({
width:300,
height:400,
cropping:true
}).then(image =>
{
this.onSelectedImage(image);
console.log(image);
})
};
choosePhotoFromLibrary = () =>{
ImagePicker.openPicker({
width:300,
height:400,
cropping:true
}).then(image =>{
this.onSelectedImage(image);
console.log(image);
})
};
onClickAddPhoto = () => {
const BUTTONS = ['Take Photo', 'Choose Photo Library', 'Cancel'];
ActionSheet.show({
options: BUTTONS,
cancelButtonIndex: 2,
title: 'Select a Photo'
},
buttonIndex => {
switch (buttonIndex) {
case 0:
this.takePhotoFromCamera();
break;
case 1:
this.choosePhotoFromLibrary();
break;
default:
break;
}
})
}
renderItem = ({item,index}) =>{
return(
<View>
<Image
source={item.url}
style={styles.itemImage}
/>
</View>
)
};
render(){
let {content,btwPressStyle} = styles;
let {fileList } = this.state;
return(
<Root>
<View style={content}>
<Text>Sample React Native Add Image</Text>
<FlatList
data={fileList}
renderItem={this.renderItem}
keyExtractor={(item,index) => index.toString()}
extraData={this.state}
/>
<TouchableOpacity onPress={this.onClickAddPhoto}
style={styles.btwPressStyle}>
<Text>Add Photo</Text>
</TouchableOpacity>
</View>
</Root>
)
}
};
const styles = StyleSheet.create({
content:{
flex:1,
alignItems:'center',
marginTop:50
},
btwPressStyle:{
backgroundColor:'blue',
height:50,
width:100,
alignItems:'center'
},
itemImage:{
backgroundColor:'#2F455C',
height:150,
width:width-60,
borderRadius:8,
resizeMode:'contain'
}
})
After running this it is giving the following error:
TypeError:null is not an object(evaluating '_reactNativeImageCropPicker.default.openPicker')
Can you please help me with the directions of how to give permission?Thanks in Advance.

onPress not working in React Native Flatlist

My onPress handler is not working when someone clicks on Flatlist item.
Video of this issue
https://u.pcloud.link/publink/show?code=XZWGOUkZmDLPeKQOQJJzxnqFB8Q21X3acT7k
Here is the code:
import React, { useState, useEffect } from 'react';
import { View, Text, Image, FlatList, ActivityIndicator } from 'react-native';
import { TouchableNativeFeedback } from 'react-native-gesture-handler';
import axios from 'axios';
export default function _AjaxApp() {
const [postList, setPostList] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [isLoading, setIsLoading] = useState(false);
const loadData = (append = false) => {
let url = "https://edristi.in/wp-json/wp/v2/posts?per_page=20&page=" + currentPage;
setIsLoading(true);
setCurrentPage(currentPage + 1);
axios.get(url).then((r) => {
if (append) {
setPostList(postList.concat(r.data));
} else {
setPostList(r.data);
}
setIsLoading(false);
}).catch((e) => {
console.log(e);
});
}
useEffect(() => {
loadData();
}, [])
let Loader = <></>
if (isLoading) {
Loader = <ActivityIndicator></ActivityIndicator>
}
return (
<View>
<View style={{padding:20, backgroundColor:"#4342fe"}}>
<Text style={{color:"white"}}>Edristi App</Text>
</View>
<FlatList
data={postList}
renderItem={({ item, index, separators }) => <PostCard postList={postList} {...item} index={index} />}
keyExtractor={r => r.id + "-" + Math.random().toString()}
removeClippedSubviews={true}
maxToRenderPerBatch={2}
ListFooterComponent={Loader}
onEndReachedThreshold={0.5}
onEndReached={() => {
loadData(true);
}}
/>
</View>
);
}
class PostCard extends React.PureComponent {
onPressHandler() {
console.log("Clicked");
alert("Clicked");
}
render() {
let image = <></>
if (this.props.jetpack_featured_media_url.trim() !== "") {
image = <Image style={{ flex: 1 }} source={{
//uri: this.props.featuredimage,
uri: this.props.jetpack_featured_media_url,
}} />
}
// console.log(this.props.jetpack_featured_media_url);
return <TouchableNativeFeedback onPress={()=>{
this.onPressHandler();
}}>
<View style={{ margin: 10 }}>
<Text style={{ fontSize: 17, lineHeight: 23, fontWeight: "600" }}>{ this.props.title.rendered}</Text>
</View></TouchableNativeFeedback>
}
}
Try to import 'TouchableNativeFeedback' from 'react-native' instead of 'react-native-gesture-handler'.