如何防止 React 重新渲染整个组件?

时间:2021-04-02 00:13:23

标签: javascript reactjs react-native react-hooks use-state

每次在 State 上设置分类时,如何防止相机重新渲染? 重新渲染整个组件会导致黑屏半秒,如下所示。我只想更新文本,这可能吗?或者我应该制作一个单独的组件? 我已经看到 React.memo() 可能是一个解决方案,但无法使其工作

enter image description here

谁能帮我解决这个问题?

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,
  },
});

1 个答案:

答案 0 :(得分:1)

创建两个子组件,一个用于相机,另一个用于文本。

使用context来存储你的分类状态,那么当你在你的上下文中改变分类的状态时,只有你的分类状态的消费者(文本组件子)会发生变化。