0

I'm using react-native and react-navigation v5. I wanted to navigate to another page after the function executes.
I am using react native camera. After I take the picture I want the app to navigate to another page with the data of the image. is there a way to do it.

import React, { PureComponent } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { RNCamera } from 'react-native-camera';

const PendingView = () => (
  <View
    style={{
      flex: 1,
      backgroundColor: 'lightgreen',
      justifyContent: 'center',
      alignItems: 'center',
    }}
  >
    <Text>Waiting</Text>
  </View>
);

class CameraComponent extends PureComponent {
  render() {
    return (
      <View style={styles.container}>
        <RNCamera
          style={styles.preview}
          type={RNCamera.Constants.Type.back}
          flashMode={RNCamera.Constants.FlashMode.on}
          androidCameraPermissionOptions={{
            title: 'Permission to use camera',
            message: 'We need your permission to use your camera',
            buttonPositive: 'Ok',
            buttonNegative: 'Cancel',
          }}
          androidRecordAudioPermissionOptions={{
            title: 'Permission to use audio recording',
            message: 'We need your permission to use your audio',
            buttonPositive: 'Ok',
            buttonNegative: 'Cancel',
          }}
        >
          {({ camera, status, recordAudioPermissionStatus }) => {
            if (status !== 'READY') return <PendingView />;
            return (
              <View style={{ flex: 0, flexDirection: 'row', justifyContent: 'center' }}>
                <TouchableOpacity onPress={() => this.takePicture(camera)} style={styles.capture}>
                  <Text style={{ fontSize: 14 }}> SNAP </Text>
                </TouchableOpacity>
              </View>
            );
          }}
        </RNCamera>
      </View>
    );
  }

  takePicture = async function(camera) {
    const options = { quality: 0.5, base64: true };
    const data = await camera.takePictureAsync(options);
    //  eslint-disable-next-line
    console.log(data.uri);
  };
}

export default CameraComponent
akram-adel
  • 920
  • 7
  • 8
zaid mohammad
  • 67
  • 2
  • 10

1 Answers1

2

If CameraComponent is one of the screens of your navigation, then you should make it as a normal component because it will receive a navigation param that you will use it in navigation like so:

class CameraComponent extends Component({navigation}) {
...
  takePicture = async function(camera) {
    const options = { quality: 0.5, base64: true };
    const data = await camera.takePictureAsync(options);
    //  eslint-disable-next-line
    console.log(data.uri);
    navigation.navigate('any-other-page', {
      imgData: data
    });
  };
}

More info can be found in Moving between screens docs of react-navigation
And info about passing data and getting data can be found in Passing parameters to routes docs


There are cases where CameraComponent will not be part of the screens of the navigation, rather, it will be a child/nested child of it.
There are three different solutions to this:

If the CameraComponent is a direct child of the navigation screen
Then you simply pass the navigation prop to the child, like so:

class ParentScreen extends Component({navigation}) {
...
  <CameraComponent navigation={navigation} />
}

and then use the navigation prop as we did above.

If the CameraComponent is a deeply nested child of the navigation screen
This will be quite difficult to explain here, but in short, you will use react context to do this if you want to keep your react components as class components

If the CameraComponent is a deeply nested child of the navigation screen
You can change your react components to be functional components and then use the more easy way: useNavigation Hook like so:

function CameraComponent () {
  const navigation = useNavigation();
...
  takePicture = async function(camera) {
    const options = { quality: 0.5, base64: true };
    const data = await camera.takePictureAsync(options);
    //  eslint-disable-next-line
    console.log(data.uri);
    navigation.navigate('any-other-page', {
      imgData: data
    });
  };
}```
akram-adel
  • 920
  • 7
  • 8
  • I used the way of passing the navigation param inside the camera component. But it is giving me as error. Cant find variable navigation – zaid mohammad Sep 05 '20 at 10:35
  • Did you check [this explaination](https://reactnavigation.org/docs/navigating/#navigating-to-a-new-screen)? there is a Snack working example below it that you can check for more details – akram-adel Sep 05 '20 at 10:44
  • I found a way to navigate to another screen, I used this.props.navigation.navigate("Screen", { imgData: data })...... It worked. Now i am wondering how can i receive the data in the other screen? – zaid mohammad Sep 05 '20 at 10:49
  • You can check [this part](https://reactnavigation.org/docs/params/). Simply to pass params to a route, you do `props.navigation.navigate('RouteName', { /* params go here */ })` and to read the params in your screen, you do `props.route.params`. All those links and explanations are in the answer :) – akram-adel Sep 05 '20 at 10:54
  • i am getting an error in my other screen. undefined is not an object (evaluating '_this.props' – zaid mohammad Sep 05 '20 at 10:58
  • Is the other screen/component direct child of the navigation screens? if not, then you will get this error. To solve it, you can use one of the three methods in the answer to pass the `route.params` props to that component. Can you create a minimal example of your code in a sandbox for me to see the structure of your navigation tree to give you better explanations? – akram-adel Sep 05 '20 at 11:04
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/221010/discussion-between-zaid-mohammad-and-akram-adel). – zaid mohammad Sep 05 '20 at 11:05
  • https://codesandbox.io/s/long-thunder-1mms6?file=/src/App.js – zaid mohammad Sep 05 '20 at 11:19