How to access camera in react native expo? - react-native

This is the code I am implementing to access camera in React Native Expo App. But this code is not working. It only shows blank screen and nothing else. Please suggest me if any changes required or any alternate method to implement this.
import React, { useState, useEffect } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { Camera } from 'expo-camera';
export default function App() {
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={{ flex: 1 }}>
<Camera style={{ flex: 1 }} type={type}>
<View
style={{
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
}}>
<TouchableOpacity
style={{
flex: 0.1,
alignSelf: 'flex-end',
alignItems: 'center',
}}
onPress={() => {
setType(
type === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back
);
}}>
<Text style={{ fontSize: 18, marginBottom: 50, color: 'red' }}> Flip </Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}

It looks like somehow you have denied permission in App. Also In the code, if hasPermission is null you will see a blank page.
Note: In Ios, if you have denied or granted permission once, then the app will never show permission popup again until you use linking and let the user enable permission from setting.

It looks like the Camera.requestPermissionsAsync is now deprecated. You might try using Camera.requestCameraPermissionsAsync(). After I updated my code the deprecation notice disappeared.

The Camera component shouldn't in the <SafeAreaView>
<YOUR_CAMERA_COMPONENT /> /* <-- when outside the <SafeAreaView> , it work!*/
<SafeAreaView>
<YOUR_CAMERA_COMPONENT /> /* <-- it will show blank view */
</SafeAreaView>
I solved the problem when removed the <Camera /> from <SafeAreaView />

Firstly i am using:
"expo": "~40.0.0",
now im upgrading the cli and then using expo upgrade and everything fix itself:
"expo": "^41.0.0",
"expo-camera": "~11.0.2",
"expo-cli": "^4.4.1",
"expo-image-picker": "~10.1.4",
"expo-status-bar": "~1.0.4",
"firebase": "8.2.3",

The emulator camera doesn't support this library , try using in Android or Ios device and it will work perfectly fine.
Please check this example or the original Expo-camera library.
Hope it helps .feel free for doubts

I saw your code and I feels this code same as a expo-camera documentation.
I think you are trying this code on Emulator/Simulator . please try once on
Physical Device. because emulator doesn't support camera. you can read the document in brief https://docs.expo.io/versions/latest/sdk/camera/#requestpermissionsasync

Related

React native Responsive layout in Functional component

Below is the basic code for Responsive layout using npm package(react-native-responsive-screen). This is working fine as expected in Class component. But, I want to change the below code to Functional component. I have almost changed everything. Initially no error when i load the app in portrait/landscape mode. Once i change it to landscape/portrait, it will come up with some error.
Here is the link of Original source. https://github.com/marudy/react-native-responsive-screen/blob/master/examples/responsive-screen-orientation-change/README.md
import React, { useEffect, useState } from 'react';
import { StyleSheet, Dimensions } from 'react-native';
import { Container, View, Button, Text} from "native-base";
import {widthPercentageToDP as wp,
heightPercentageToDP as hp,
listenOrientationChange as lor,
removeOrientationListener as rol } from 'react-native-responsive-screen';
const Responsive = () =>
{
useEffect( () =>
{
lor();
return () => rol()
},[])
const styles = StyleSheet.create({
container: { flex: 1, alignItems: 'center', justifyContent:'center' },
title: {
backgroundColor: 'gray',
height: hp('10%'),
width: wp('80%'),
alignItems: 'center',
justifyContent:'center',
marginVertical: wp('10%'),
},
myText: {
textAlign:'center',
color:'white',
fontSize: hp('5%') // End result looks like the provided UI mockup
},
buttonStyle:
{
height: hp('8%'), // 70% of height device screen
width: wp('30%'),
marginHorizontal: wp('10%'),
},
buttonContainer:
{
flexDirection:'row',
marginBottom: wp('10%'),
},
paraContainer:
{
width: wp('80%'),
},
paraText:
{
textAlign:'justify'
}
});
return (
<Container>
<View style={styles.container}>
<View style={styles.title}>
<Text style={styles.myText}>Screen title with 50% width</Text>
</View>
<View style={styles.buttonContainer}>
<Button success style={styles.buttonStyle}><Text>Button 1</Text></Button>
<Button success style={styles.buttonStyle}><Text>Button 2</Text></Button>
</View>
<View style={styles.paraContainer}>
<Text style={styles.paraText}>
As mentioned in "How to Develop Responsive UIs with React Native" article, this solution is
already in production apps and is tested with a set of Android, iOS emulators of different
screen
specs, in order to verify that we always have the same end result.
</Text>
</View>
</View>
</Container>
);
}
export default Responsive;
Thanks in Advance.
It is not due to your code, it is due to library limitation. Current version of library still does not support functional components.
There is an open issue and PR regarding that open
issue: https://github.com/marudy/react-native-responsive-screen/issues/82
PR: https://github.com/marudy/react-native-responsive-screen/pull/70
If you still want to continue with this library, just use the head of that PR in your package.json and it should work.
"react-native-responsive-screen": "marudy/react-native-responsive-screen#70/head",
Make sure to delete node_module and perform yarn or npm install

React-native : show content on two rows

I want to show 6 options per row instead of showing only one option per row.
I'm still new in react-native
Here is the code :
import React from 'react';
import {fromJS} from 'immutable';
import {ScrollView, StyleSheet, TouchableOpacity} from 'react-native';
import {Text} from 'src/components';
import Option from './OptionVariable';
import {checkOption} from 'src/modules/product/helper';
import {margin} from 'src/components/config/spacing';
class AttributeVariable extends React.Component {
onSelectOption = (option) => {
const {onSelectAttribute, attribute} = this.props;
onSelectAttribute(attribute.get('id'), attribute.get('name'), option.get('option'));
};
render() {
const {attribute, meta_data, variations} = this.props;
// Attribute selected
const attributeSelected = meta_data.find(attr => attr.get('id') === attribute.get('id') && attr.get('name') === attribute.get('name'));
return (
<>
<Text>
{attribute.get('name')}: <Text colorSecondary>{attributeSelected ? attributeSelected.get('option') : ''}</Text>
</Text>
<ScrollView
style={styles.attribute}
vertical
showsHorizontalScrollIndicator={false}>
{attribute.get('options').map(option => {
const disabled = meta_data.size === 0 ? false : !checkOption(variations, meta_data, fromJS({
id: attribute.get('id'),
name: attribute.get('name'),
option: option.get('option'),
}));
return (
<TouchableOpacity
activeOpacity={disabled ? 1 : 0}
key={option}
onPress={() => disabled ? {} : this.onSelectOption(option)}
>
<Option
type={attribute.get('type')}
selected={attributeSelected && option.get('option') === attributeSelected.get('option')}
disabled={disabled}
option={option}
/>
</TouchableOpacity>
)
})}
</ScrollView>
</>
);
}
}
const styles = StyleSheet.create({
attribute: {
marginTop: margin.small,
},
});
export default AttributeVariable;
Here is how it looks :
I hope everything is clear to you.
Sorry for my bad english it's not my main language....
Thanks in advance for any help.
you can say in your attribute style:
attribute: {
marginTop: margin.small,
flexDirection: 'row'
},
so it should align in rows instead of columns
That should help you to learn more about styling components in react native: https://facebook.github.io/react-native/docs/flexbox
Try using the Flatlist (instead of ScrollView) component passing the horizontal={true} props.
Like this:
FlatList
horizontal={true}
data={attribute.option}
renderItem={({ item }) => "Pass your component"}
keyExtractor={item => item.id}
/>
UPDATE 2 :
I used View instead of ScrollView with the following styles and it worked just fine..
<View style={[styles.container, ]}
horizontal
style={{AlignContent: 'flex-start', flexDirection: 'row', alignItems: 'flex-start',}}
style={styles.attribute}
showsHorizontalScrollIndicator={false}>
UPDATE 1 :
I solved the problem using this :
container: {
marginTop: margin.small,
flexDirection: 'row-reverse',
position: 'relative',
width: 'auto',
alignSelf: 'stretch',
maxWidth: 29,
height: 29,
marginBottom: margin.big,
borderRadius: borderRadius.base,
borderWidth: 1,
},
I changed the size of option so all of them appear on the same row (not exactly what I want but it works)
If anyone have a better answer please share.

React Native: I am getting error while trying to get image from https://cataas.com api

I am getting SyntaxError: Json Parse error: JSON Parse error: Unrecognized token '<'
I'm using https://cataas.com api for a react native app, my task is to generate a list of random kitten images. I tried using fetch method, but also i get error sorce.uri should not be an empty string. How can i solve this problem?
Here is my code:
import React, { Component } from 'react';
import {
Image,
StyleSheet,
Text,
View,
FlatList
} from 'react-native';
class App extends Component {
state = {
photos: '',
}
componentDidMount() {
fetch('https://cataas.com/cat?width=100')
.then(res => res.json())
.then(data => {
this.setState({
photos: data
})
.catch(err => {
console.log('error', err);
alert(err)
})
})
}
render() {
console.log(this.state.photos)
return (
<View style={styles.container}>
<Image
source={{url: this.state.photos}}
style={{height: 100, width: 100}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
}
});
export default App;
There is a typo in your code
Replace url with uri as in the docs
<Image
source={{uri: this.state.photos}}
style={{height: 100, width: 100}}
/>
You don't have to call this api manually, you could directly use the link in the Image component :
<Image
source={{uri: "https://picsum.photos/100/100"}}
style={{height: 100, width: 100}}
/>
EDIT:
Ok it's not as easy as I thought !
I created a first basic version : https://snack.expo.io/#sanjar/so-53434400
And contrary to what I thought it's always the same picture that is displayed.
It's because of react-native cache system that see the same url and decide to not execute the http request again.
then I checked the doc and founda way to fix this issue, but for ios only
I just had to change :
source={{uri: "https://source.unsplash.com/random"}}
by :
source={{uri: "https://source.unsplash.com/random", cache: 'reload'}}
It should work on ios (I don't have a mac with me now), for android I don't know yet, I'll probably investigate later.

setNativeProps Change Value for Text Component React Native Direct Manipulation

I want to directly update the value of a component due to performance reasons.
render(){
<View>
<Text style={styles.welcome} ref={component => this._text = component}>
Some Text
</Text>
<TouchableHighlight underlayColor='#88D4F5'
style={styles.button}>
<View>
<Text style={styles.buttonText}
onPress={this.useNativePropsToUpdate.bind(this)}>
Iam the Child
</Text>
</View>
</TouchableHighlight>
</View>
}
This is the method I use to update the text component. I dont know if I am setting the right attribute/ how to figure out which attribute to set:
useNativePropsToUpdate(){
this._text.setNativeProps({text: 'Updated using native props'});
}
Essentially trying to follow the same approach from this example:
https://rnplay.org/plays/pOI9bA
Edit:
When I attempt to explicitly assign the updated value:
this._text.props.children = "updated";
( I know this this the proper way of doing things in RN ). I get the error "Cannot assign to read only property 'children' of object'#'"
So maybe this is why it cant be updated in RN for some reason ?
Instead of attempting to change the content of <Text> component. I just replaced with <TextInput editable={false} defaultValue={this.state.initValue} /> and kept the rest of the code the same. If anyone know how you can change the value of <Text> using setNativeProps OR other method of direct manipulations. Post the answer and ill review and accept.
The text tag doesn't have a text prop, so
this._text.setNativeProps({ text: 'XXXX' })
doesn't work.
But the text tag has a style prop, so
this._text.setNativeProps({ style: { color: 'red' } })
works.
We can't use setNativeProps on the Text component, instead, we can workaround and achieve the same result by using TextInput in place of Text.
By putting pointerEvent='none' on the enclosing View we are disabling click and hence we can't edit the TextInput (You can also set editable={false} in TextInput to disbale editing)
Demo - Timer (Count changes after every 1 second)
import React, {Component} from 'react';
import {TextInput, StyleSheet, View} from 'react-native';
class Demo extends Component {
componentDidMount() {
let count = 0;
setInterval(() => {
count++;
if (this.ref) {
this.ref.setNativeProps({text: count.toString()});
}
}, 1000);
}
render() {
return (
<View style={styles.container} pointerEvents={'none'}>
<TextInput
ref={ref => (this.ref = ref)}
defaultValue={'0'}
// editable={false}
style={styles.textInput}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 0.7,
justifyContent: 'center',
alignItems: 'center',
},
textInput: {
fontSize: 60,
width: '50%',
borderColor: 'grey',
borderWidth: 1,
aspectRatio: 1,
borderRadius: 8,
padding: 5,
textAlign: 'center',
},
});
export default Demo;
As setNativeProps not solving the purpose to alter the content of <Text />, I have used below approach and is working good. Create Simple React Component like below...
var Txt = React.createClass({
getInitialState:function(){
return {text:this.props.children};
},setText:function(txt){
this.setState({text:txt});
}
,
render:function(){
return <Text {...this.props}>{this.state.text}</Text>
}
});

React Native Webview not loading any url (React native web view not working)

I am trying to implement react native webview component in my application, but the web view is not loading any url its just showing the white page.
var React = require('react-native');
var{
View,
Text,
StyleSheet,
WebView
} = React;
module.exports = React.createClass({
render: function(){
return(
<View style={styles.container}>
<WebView source={{uri: 'https://m.facebook.com'}} style= {styles.webView}/>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex:1,
backgroundColor: '#ff00ff'
},webView :{
height: 320,
width : 200
}
});
Below is the screenshot of the output .
I had this issue. WebView would render when it was the only component returned, but not when nested in another View component.
For reasons I'm not entirely sure of the issue was resolved by setting a width property on the WebView component.
class App extends React.Component {
render() {
return (
<View style={styles.container}>
<WebView
source={{uri: 'https://www.youtube.com/embed/MhkGQAoc7bc'}}
style={styles.video}
/>
<WebView
source={{uri: 'https://www.youtube.com/embed/PGUMRVowdv8'}}
style={styles.video}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'space-between',
},
video: {
marginTop: 20,
maxHeight: 200,
width: 320,
flex: 1
}
});
I'm facing same issue. What I observed is that WebView doesn't work if it's nested. If component returns just WebView, then everything is fine.
Using the answers from other users, I was able to get my react native with webview working both inside a view and outside a view. My problem came down to two things. Being on the android emulator and behind a proxy, I just had to go to my browser (chrome) in the android emulator and sign in to the corporate proxy. Secondly, some sites work and others will not work. Whether the webview was nested or not inside of a View tag, some sites like cnn.com and slack.com etc will work fine, but no matter what settings I tried for google.com it wouldn't work (even though the proxy will definitely allow google.com) Lastly, when I rebuild my application and push to the emulator the new app, sometimes it took an inordinately long time to load any site. But once the site was loaded, the links are quick and responsive. So if you don't at first see something after a build, also be patient. Hope this helps someone else.
My final app.js
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Dimensions
} from 'react-native';
import { WebView } from 'react-native';
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width;
type Props = {};
export default class App extends Component<Props> {
render() {
return (
<View style={{flex:1}}>
<WebView
style={styles.webview}
source={{uri: 'https://www.slack.com'}}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={false}
scalesPageToFit={true} />
</View>
);
}
}
const styles = StyleSheet.create({
webview: {
flex: 1,
backgroundColor: 'yellow',
width: deviceWidth,
height: deviceHeight
}
});
WebView works well on Android. However you need to enable javascript and dom storage for some web pages.
<WebView style={styles.webView}
source={{uri: 'https://google.com/'}}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={true}
>
</WebView>
If you want the component to render the entire page, you need to wrap it with View that has flex: 1. The code below works for me:
<View style={{flex:1, alignItems: 'flex-end'}}>
<WebView
source={{uri: this.state.webContentLink}}
startInLoadingState={true}
scalesPageToFit={true} />
</View>
WebView is being moved to react-native-webview
.
None of the other answers worked except this method:
npm install --save react-native-webview
Then use it as follows:
<View style={{ flex: 1, alignItems: 'flex-end' }}>
<WebView
source={{
uri: 'https://www.yahoo.com',
}}
startInLoadingState={true}
scalesPageToFit={true}
style={{
width: 320,
height: 300,
}}
/>
</View>
<View>
<WebView
source={{uri: this.props.link}}
style={styles.webview}
javaScriptEnabled={true}
domStorageEnabled={true}
startInLoadingState={true}
/>
</View>
and style as follows:
const React = require('react-native');
const { Dimensions } = React;
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width;
export default {
webview: {
width: deviceWidth,
height: deviceHeight
}
};
All this to deal with bad webview dimension, so just set a specific height and specific width too (deviceHeight and deviceWidth as the example above).
As of June 2020 (noting the date because React Native answers seem to become out-of-date quickly), the simplest solution to this appears to be:
import React from 'react'
import { View, StyleSheet } from 'react-native'
import { WebView } from 'react-native-webview'
export const ComponentWithWebView = () => {
return (
<View style={styles.view}>
<WebView source = {{uri: 'https://www.google.com/'}} />
</View>
)
}
const styles = StyleSheet.create({
view: {
alignSelf: 'stretch',
flex: 1,
}
}
This results in a WebView filling the available space and being nested within a View. I believe the typical problems faced when placing a WebView within a View is that View expects children to force the View to expand (that is, a Text component would take up some amount of width and height which the View then accommodates). WebView, on the other hand, expands to the size of the parent component unless a style is passed specifying the width. Therefore, a simple <View><WebView /></View> results in a 0 width and nothing shown on the screen. The earlier solutions of setting the WebView width work well but require either the device dimensions to be fetched (which might not be the desired width) or for the View to have an onLayout function AND have some way to expand the View to the desired space. I found it easiest to just apply the flex: 1 and alignSelf: 'stretch' for the View to fill the space as desired and then WebView to automatically follow suit.
Hope this helps someone before it becomes obsolete!
I ran into the same issue recently. And I found that
alignment: 'center'
was causing the issue for me. I commented it and the webView got loaded immediately.
I found the solution here :
https://github.com/facebook/react-native/issues/5974
'brunocvcunha's' response worked for me.
Let me give the simplest example which will work seamlessly:
import React from 'react';
import { WebView } from 'react-native';
export default class App extends React.Component {
render() {
return (
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
/>
);
}
}
Do not add your WebView component within a view that created problem and webview url is not rendered rather styles of view will be shown.
I had the same issue and spent a day attempting to fix it. I copied in the UIExplorer webview example, and that didn't work.
I ultimately ended up upgrading react and creating a new react-native project and copying the files in there, and that fixed it.
I wish I had a better answer as to why that fixed it, but hopefully that helps
Below is piece of the code which worked for me.
render: function(){
return(
<View style={styles.container}>
<WebView url={'https://m.facebook.com'} style= {styles.webView}/>
</View>
);
}
I am doing React Native Webview, Could you please suggest me how to makeWebview loading the uri
render() {
return (
<Modal
animationType="slide"
ref={"webModal"}
style={{
justifyContent: 'center',
borderRadius: Platform.OS === 'ios' ? 30 : 0,
width: screen.width,
height: screen.height,borderColor:'red',
borderWidth: 5
}}
position='center'
backdrop={false}
onClosed={() => {
// alert("Modal closed");
}}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 20, top: 10 }} >
<Text style={{ fontSize: 24, fontWeight: '700' }}>
Interests
</Text>
<Icon name="ios-close" size={40} color='purple' onPress={() => { this.refs.webModal.close() }} />
</View>
<WebView
source={{ uri: this.state.link }}
style={{ marginTop: 20,borderColor:'green',
borderWidth: 5 }}
/>
</Modal>
);
}
}
import { WebView } from 'react-native'; is deprecated
use below line instead
npm install react-native-render-html#4.1.2 --save
then
import HTML from 'react-native-render-html';
react-native-render-html starting with version 4.2.0, react-native-webview is now a peer dependency. As a result, you need to install it yourself.
Try
<WebView
source={{ uri: "https://inhall.in/" }}
style={Styles.webView}
javaScriptEnabled={true}
scalesPageToFit />
javaScriptEnabled={true} might help