I am relatively new to React-Native and mobile app development. I am trying to create a clone of Instagram. And in the post screen what I do is I have a button Camera
and once I click on it, that should take me to CameraView
screen. And in the CameraView
screen I will take a picture using expo-camera
and save the picture in a variable. So here, I want to export the picture and then import it in my Post
screen, so that the user can have a preview of what the picture looks like before uploading. And another thing to note is that, the Post
screen will by default have a Placeholder image and once the image is taken the placeholder image has to be replaced with the image.
I tried this code but it didnt work.
My Post
screen :-
import { View, Text, Image, TextInput } from 'react-native';
import React, { useState, useEffect } from 'react'
import * as Yup from 'yup';
import { Formik } from 'formik'
import { Button, Divider } from 'react-native-elements';
import { useNavigation } from '@react-navigation/native';
import CameraView, { takePicture } from '../../screens/CameraView';
const PLACEHOLDER_IMG = require('../../assets/defImg.png')
const uploadPostSchema = Yup.object().shape({
caption: Yup.string().max(2200, 'Caption cannot exceed character limit.')
})
const FormikPostUploader = ({route}) => {
const [thumbnailUrl, setThumbnailUrl] = useState(PLACEHOLDER_IMG)
const navigation = useNavigation()
const handleCameraPress = () => {
UserImage = takePicture()
setThumbnailUrl(UserImage)
navigation.navigate('CameraView')
}
return (
<Formik
initialValues={{ imageUrl: '', caption:'' }}
onSubmit={(values) => console.log(values)}
validationSchema={uploadPostSchema}
validateOnMount={true}>
{({
handleBlur,
handleChange,
handleSubmit,
values,
errors,
isvalid
}) => (
<>
<View style={{ margin: 20, justifyContent: 'space-between', flexDirection: 'row' }}>
<Image source={thumbnailUrl} />
<View style={{ flex: 1, margin: 15 }}>
<TextInput
placeholder='Write a caption...'
placeholderTextColor='gray'
multiline={true}
style={{ color: 'white', fontSize: 17 }}
onChangeText={handleChange('caption')}
onBlur={handleBlur('caption')}
value={values.caption}
/>
</View>
</View>
<Divider width={0.5} orientation='vertical'/>
<View style={{ alignItems: 'center', marginTop: 15 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', color: 'white' }}>Choose Image</Text>
</View>
<View style={{ justifyContent: 'space-between', flexDirection: 'column', margin: 20 }}>
<View style={{ justifyContent: 'space-between', flexDirection: 'row', margin: 30 }}>
<Button title='Camera' onPress={handleCameraPress}/>
<Button title='Gallery' onPress={() => navigation.navigate('GalleryView')} />
</View>
<Button onPress={handleSubmit} title='Post' disabled={isvalid} />
</View>
</>
)}
</Formik>
)
}
export default FormikPostUploader
And my CameraView
screen :-
import { View, Text, Image, StyleSheet, Button } from 'react-native'
import React, {useState, useEffect} from 'react'
import { Camera } from 'expo-camera'
import { TouchableOpacity } from 'react-native'
import { useNavigation } from '@react-navigation/native'
import { PLACEHOLDER_IMG } from '../components/newPost/FormikPostUploader'
export const takePicture = async(camera) => {
const data = await camera.takePictureAsync(null)
return data.uri
}
const Header = () =>{
const navigation = useNavigation()
return (
<View style = {styles.headerContainer}>
<TouchableOpacity style = {{marginBottom:15}} onPress={() => navigation.goBack()}>
<Image source = {require('../assets/back.png')} style = {{width:35, height:35, margin:20}}/>
</TouchableOpacity>
<Text style={{color:'white', fontWeight: '700', fontSize:20, marginRight: 25, marginTop:35, marginBottom:15}}>New Post</Text>
<Text> </Text>
</View>
)
}
const CameraView = () => {
const UserImage = takePicture()
const navigation = useNavigation()
const [hasCameraPermission, setHasCameraPermission] = useState(null)
const [thumbnailUrl, setThumbnailUrl] = useState(PLACEHOLDER_IMG)
const [camera, setCamera] = useState(null)
const [type, setType] = useState(Camera.Constants.Type.back)
const captureImage = async () => {
if (camera) {
const UserImage = await takePicture(camera)
setThumbnailUrl(UserImage)
}
}
useEffect(() => {
(async() => {
const cameraStatus = await Camera.requestCameraPermissionsAsync()
setHasCameraPermission(cameraStatus.status === 'granted')})()},
[])
if (hasCameraPermission === null) {
return <View/>
}
if (hasCameraPermission === false){
return <Text>Enable access for Camera to proceed</Text>
}
return (
<View style={{ flex: 1, backgroundColor: 'black'}}>
<Header/>
<Camera
ref = {ref => setCamera(ref)}
style={styles.fixedRatio}
type={type}
ratio={'1:1'}/>
<View style = {styles.cameraContainer}>
<TouchableOpacity onPress={() => {setType(type === Camera.Constants.Type.back ? Camera.Constants.Type.front : Camera.Constants.Type.back)}}>
<Image source={require('../assets/turn-camera.png')} style = {{width:70, height:70, margin: 15}}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => {captureImage(), navigation.goBack(), console.log(UserImage)}}>
<Image source={require('../assets/camera-shutter.png')} style = {{width:70, height:70, marginRight:60}}/>
</TouchableOpacity>
</View>
</View>
)
}
const styles = StyleSheet.create({
cameraContainer: {
flex:0.15,
backgroundColor: 'black',
flexDirection:'row',
justifyContent: 'space-between',
alignItems: 'center',
},
fixedRatio: {
flex:0.99,
aspectRatio:0.9
},
headerContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor:'black'
},
icon: {
width:25,
height: 25,
marginHorizontal:15,
marginTop:30,
},
iconContainer: {
flexDirection:'row',
justifyContent: 'space-between',
height:50,
},
}
)
export default CameraView
Am I doing anything wrong. Can you help me fix this. Thanks in advance!