0

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!

Pranav J
  • 82
  • 6

0 Answers0