Unhandled promise rejection: TypeError: null is not an object (evaluating camera.pictureSize)

6.9k views Asked by At

I am creating a react-native app to use the expo-camera module.

So I declared a camera variable as

let camera: any = null;

I am passing a reference to this from the return as:

<Camera style = {{flex: 1, opacity: camOpacity}}
          type = {state.type}
          ratio = "2:1"
          ref = {async (ref) => (camera = ref)}>

But when I run the app, it starts normally but on trying to take a picture it gives the error:

[Unhandled promise rejection: TypeError: null is not an object (evaluating 'camera.pictureSize')]

This error is occuring from :

console.log(camera.pictureSize);

But it is also happening at:

console.log(" --> Taking image");
    const opts = {
       skipProcessing: true,
       exif: false,
       quality: 0
    };
    let photo = await camera.takePictureAsync(opts);

from the camera.takePictureAsync(opts) part when I am commenting out the console.log(camera.pictureSize);

For some reason the reference isn't getting detected maybe.

My package.json is:

"dependencies": {
    "expo": "~39.0.2",
    "expo-2d-context": "0.0.2",
    "expo-asset": "~8.2.0",
    "expo-camera": "~9.0.0",
    "expo-gl": "~9.1.1",
    "expo-image-manipulator": "~8.3.0",
    "expo-permissions": "~9.3.0",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "https://github.com/expo/react-native/archive/sdk-39.0.3.tar.gz",
    "react-native-web": "~0.13.12",
    "react-native-screens": "~2.10.1",
    "react-native-svg": "~12.1.0",
    "mem": "^8.0.0",
    "@unimodules/core": "~5.5.0"
  }

I read there were some such errors in the current expo-camera release, but even if I downgrade the packages and dependencies it is still being persistent.

Any help would be really appreciated.

EDIT:

const photo = async (): Promise<CameraCapturedPicture> | undefined  => {
      if(camera){
        console.log(" --> Taking image");
        const opts = {
          skipProcessing: true,
          exif: false,
          quality: 0
        };
        return await camera.takePictureAsync(opts);
      }
    }
    
    console.log(" --> Resizing image");
    const {uri} = await ImageManipulator.manipulateAsync(
      photo.uri,
      [
        { resize: {width: 256, height: 512}},
        { crop: {originX: 0, originY: 128, width: 256, height: 256}}
      ]
    );

I changed the code according to Linda's kind suggestion but now the error is that the Promise is not a valid type and photo.uri doesnt have the uri property

1

There are 1 answers

1
Linda Paiste On

You initialized the camera ref object to null. So before you call any functions on it, you need to verify that it has actually been set to a Camera and is not still null. I suspect that's the cause of the error in your take picture function. Notice in the docs that they check if (this.camera) { before calling a method on the camera.

console.log(camera.pictureSize) is just wrong even when camera is not null because that property doesn't exist. pictureSize is a prop which you pass to the Camera component. It is not a property which exists on the camera instance. You should review the documentation.

Rather than using any, you can change your variable declaration to be Camera | null and that should help you to see the properties and methods which are available.

let camera: Camera | null = null;

You can check that camera isn't null inside the method that you call to take a picture:

const takePicture = async (): Promise<CameraCapturedPicture> | undefined => {
  if (camera) {
    console.log(" --> Taking image");
    const opts = {
      skipProcessing: true,
      exif: false,
      quality: 0
    };
    return await camera.takePictureAsync(opts);
  }
};

Or you can check before calling the method and pass the camera variable into the method so that typescript knows it's not null.

const executeTakePicture = async (cam: Camera): Promise<CameraCapturedPicture> => {
  console.log(" --> Taking image");
  const opts = {
    skipProcessing: true,
    exif: false,
    quality: 0
  };
  return await cam.takePictureAsync(opts);
};

const maybeTakePicture = async (): Promise<CameraCapturedPicture> | undefined => {
  if (camera) {
    return await executeTakePicture(camera);
  } else {
    //...
  }
}