简体   繁体   中英

How to prevent React from re-rendering a whole component?

How can I prevent the camera from re-rendering every time a classification is set on the State? Re-rendering the whole component causes a black screen for half-second, as shown below. I want just the text to update, is it possible? Or should I make a separate component? I've seen React.memo() might be a solution, but couldn't make it work

在此处输入图像描述

Can anyone help me to work this around?

import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Platform, Dimensions } from 'react-native';
import { Camera } from 'expo-camera';
import * as tf from '@tensorflow/tfjs';
import * as mobilenet from '@tensorflow-models/mobilenet';
import {cameraWithTensors} from '@tensorflow/tfjs-react-native';
console.disableYellowBox = true;

  const windowWidth = Dimensions.get('window').width;
  const windowHeight = Dimensions.get('window').height;

export default function App() {


  const [classification, setClassification] = useState('');
  const [hasPermission, setHasPermission] = useState(null);
  const [mobilenetModel, setMobilenetModel] = useState(null);
  const [frameworkReady, setFrameworkReady] = useState(false);

  const TensorCamera = cameraWithTensors(Camera);

  let requestAnimationFrameId = 0;

  const textureDims = Platform.OS === "ios"? { width: 1080, height: 1920 } : { width: 1600, height: 1200 };
  const tensorDims = { width: 224, height: 224 }; 


  useEffect(() => {
    if(!frameworkReady) {
      (async () => {

        //check permissions
        const { status } = await Camera.requestPermissionsAsync();
        console.log(`permissions status: ${status}`);
        setHasPermission(status === 'granted');

        //we must always wait for the Tensorflow API to be ready before any TF operation...
        await tf.ready();

        //load the mobilenet model and save it in state
        setMobilenetModel(await loadMobileNetModel());

        setFrameworkReady(true);
      })();
    }
  }, []);



  const loadMobileNetModel = async () => {
    const model = await mobilenet.load();
    return model;
  }



  const getPrediction = async(tensor) => {
    if(!tensor) { return; }
    const prediction = await mobilenetModel.classify(tensor, 1);
 

    if(!prediction || prediction.length === 0) { return; }
    
    if(prediction[0].probability > 0.6) {

      setClassification(prediction[0].className);
    }
  }

  
  const handleCameraStream = (imageAsTensors) => {
    const loop = async () => {
      const nextImageTensor =  imageAsTensors.next().value;
      await getPrediction(nextImageTensor);
     
      requestAnimationFrameId = requestAnimationFrame(loop); 
    };
    loop();
  }


  // Helper function to show the Camera View. 
  const renderCameraView = () => {
    return <View style={styles.cameraView}>
                <TensorCamera
                  style={styles.camera}
                  type={Camera.Constants.Type.back}
                  zoom={0}
                  cameraTextureHeight={textureDims.height}
                  cameraTextureWidth={textureDims.width}
                  resizeHeight={tensorDims.height}
                  resizeWidth={tensorDims.width}
                  resizeDepth={3}
                  onReady={(imageAsTensors) => handleCameraStream(imageAsTensors)}
                  autorender={true}
                />
            </View>;
  }

  return (
    <View style={styles.container}>
        {renderCameraView()} 
      <View style={styles.header}>
        <Text style={styles.title}>
          {classification}
        </Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {

  },
  header: {
    backgroundColor: '#000',
    height: 100,
    bottom: -700,
  },
  title: {
    margin: 10,
    fontSize: 22,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#ffffff'
  },
  cameraView: {
    flex:1,
   
  },
  camera : {
    width: windowWidth,
    height: windowHeight,
  },
});

Create two child component, one for the camera and another for your text.

Use context to store your classification state, then when you change the state of classification in your context, only the consumer of your classification state (text component child) will be changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM