Gsry Senoc
Gsry Senoc

Reputation: 11

How to fix error invalid hook call react native

How can I fix this error in react native:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
import { cameraWithTensors } from "@tensorflow/tfjs-react-native";
import { Camera } from "expo-camera";
import { StatusBar } from "expo-status-bar";
import React, { useEffect, useState, useRef } from "react";
import {
  StyleSheet,
  Text,
  View,
  Platform,
  Dimensions,
  LogBox,
} from "react-native";
import * as cocoSsd from "@tensorflow-models/coco-ssd";
import { model } from "@tensorflow/tfjs";
import * as tf from "@tensorflow/tfjs";
import Canvas from "react-native-canvas";

const TensorCamera = cameraWithTensors(Camera);

const { width, height } = Dimensions.get("window");
let context = useRef<CanvasRenderingContext2D>();
let canvas = useRef<Canvas>();

export default function App() {
  const [model, setModel] = useState<cocoSsd.ObjectDetection>();

  let textureDims =
    Platform.OS === "ios"
      ? { height: 1920, width: 300 }
      : { height: 300, width: 300 };

  function handleCameraStream(images: any) {
    const loop = async () => {
      const nextImageTensor = images.next().value;
      if (!model || !nextImageTensor)
        throw new Error("No model or image tensor");
      model
        .detect(nextImageTensor)
        .then((predictions) => {
          drawRectangle(predictions, nextImageTensor);
        })
        .catch((error) => {
          console.log(error);
        });
      requestAnimationFrame(loop);
    };
    loop();
  }

  function drawRectangle(
    predictions: cocoSsd.DetectedObject[],
    nextImageTensor: any,
  ) {
    if (!context.current || !canvas.current) return;

    const scaleWidth = width / nextImageTensor.shape[1];
    const scaleHeight = height / nextImageTensor.shape[0];

    const flipHorizontal = Platform.OS == "ios" ? false : true;

    context.current.clearRect(0, 0, width, height);

    for (const prediction of predictions) {
      const [x, y, width, height] = prediction.bbox;

      const boundingBoxX = flipHorizontal
        ? canvas.current.width - x * scaleWidth - width * scaleWidth
        : x * scaleWidth;

      const boundingBoxY = y * scaleHeight;

      context.current.strokeRect(
        boundingBoxX,
        boundingBoxY,
        width * scaleWidth,
        height * scaleHeight,
      );

      context.current.strokeText(
        prediction.class,
        boundingBoxX - 5,
        boundingBoxY - 5,
      );
    }
  }

  async function handleCanvas(can: Canvas) {
    if (can) {
      can.width = width;
      can.height = height;
      const ctx: CanvasRenderingContext2D = can.getContext("2d");
      ctx.strokeStyle = "red";
      ctx.fillStyle = "red";
      ctx.lineWidth = 3;

      context.current = ctx;
      canvas.current = can;
    }
  }

  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestPermissionsAsync();
      await tf.ready();
      setModel(await cocoSsd.load());
    })();
  }, []);

  return (
    <View style={styles.container}>
      <TensorCamera
        style={styles.camera}
        type={Camera.Constants.Type.back}
        cameraTextureHeight={textureDims.height}
        cameraTextureWidth={textureDims.width}
        resizeHeight={200}
        resizeDepth={3}
        onReady={handleCameraStream}
        autorender={true}
        useCustomShadersToResize={false}
        resizeWidth={0}
      />
      <Canvas style={styles.canvas} ref={handleCanvas} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
  },
  camera: { width: "100%", height: "100%" },
  canvas: {
    position: "absolute",
    zIndex: 1000000,
    width: "100%",
    height: "100",
  },
});

Upvotes: 0

Views: 2162

Answers (3)

Dhanesh M
Dhanesh M

Reputation: 136

actual reason for this issue :- You are breaking the Rules of Hooks useRef() should call inside of the component

try this,

...
export default function App() {

  const context = useRef<CanvasRenderingContext2D>();
  const canvas = useRef<Canvas>();

  const [model, setModel] = useState<cocoSsd.ObjectDetection>();
...

}

Upvotes: 1

Prajwal Kulkarni
Prajwal Kulkarni

Reputation: 1695

An important rule of using hooks is where you're declaring it. Hooks can be declared only inside of functions, which is predominantly at the top level, meaning it can only be declared at the top level and not within any nested function, block, or inside another hook(E.g: useEffect). The reason you're getting the error is that you're simply breaking the rules of hooks by declaring it outside of the function. Move the hook declaration within the function and you should be good to go. Also, recommend changing let to const as state variables are re-built on every render and not mutated.

export default function App() {
  const context = useRef<CanvasRenderingContext2D>();
  const canvas = useRef<Canvas>();
.
.
.
.
}

Upvotes: 0

user18054155
user18054155

Reputation: 1

i think you called useRef outside of the component

...

let context = useRef();
let canvas = useRef();

export default function App() {
...
}

please call useRef inside of your App Component like this

...

    export default function App() {
      let context = useRef();
      let canvas = useRef();
      ...
    }

Upvotes: 0

Related Questions