简体   繁体   English

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

[英]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?每次在 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我已经看到 React.memo() 可能是一个解决方案,但无法使其工作

在此处输入图像描述

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.使用 上下文存储您的分类 state,然后当您在上下文中更改分类的 state 时,只会更改您的分类 state(文本组件子)的消费者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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