首页 文章

React Native:通过AsyncStorage保存图像URI并在不同的React Navigation屏幕中重新加载

提问于
浏览
0

我目前正在尝试将React Native Camera example与React Navigation v2相结合,并希望在第一个视图(称为CameraView)中拍照,将所述图片保存到AsyncStorage,导航到第二个视图(称为GalleryView)并渲染此图片从AsyncStorage到图像标记 .

我在Windows 10计算机上使用RN 0.57.1,RN-Camera 1.3.1,React Navigation 2.18.0模拟运行Android 8.0.0版的Android手机 .

这是两个视图的代码:

CameraView.js:

import React from "react";
import {
  AsyncStorage,
  Dimensions,
  StyleSheet,
  TouchableHighlight,
  View
} from "react-native";
import { RNCamera as Camera } from "react-native-camera";

const styles = StyleSheet.create({
  preview: {
    flex: 1,
    justifyContent: "flex-end",
    alignItems: "center",
    height: Dimensions.get("window").height,
    width: Dimensions.get("window").width
  },
  capture: {
    width: 70,
    height: 70,
    borderRadius: 35,
    borderWidth: 5,
    borderColor: "#FFF",
    marginBottom: 15
  }
});

class CameraView extends React.Component {
  static navigationOptions = ({ navigation }) => ({
    header: null
  });

  constructor(props) {
    super(props);
    this.state = {
      imageUri: null
    };
  }

  takePicture = async () => {
    try {
      const imageData = await this.camera.takePictureAsync({
        fixOrientation: true
      });
      this.setState({
        imageUri: imageData.uri
      });
      this._saveImageAsync();
    } catch (err) {
      console.log("err: ", err);
    }
  };

  _saveImageAsync = async () => {
    await AsyncStorage.setItem("imageUri", this.state.imageUri);
    this.props.navigation.navigate("GalleryView");
  };

  render() {
    return (
      <Camera
        ref={cam => {
          this.camera = cam;
        }}
        style={styles.preview}
        flashMode={Camera.Constants.FlashMode.off}
        permissionDialogTitle={"Permission to use camera"}
        permissionDialogMessage={
          "We need your permission to use your camera phone"
        }
      >
        <TouchableHighlight
          style={styles.capture}
          onPress={this.takePicture.bind(this)}
          underlayColor="rgba(255, 255, 255, 0.5)"
        >
          <View />
        </TouchableHighlight>
      </Camera>
    );
  }
}

export default CameraView;

GalleryView.js:

import React from "react";
import {
  AsyncStorage,
  Button,
  Dimensions,
  StyleSheet,
  Text,
  Image,
  View
} from "react-native";

const styles = StyleSheet.create({
  preview: {
    flex: 1,
    justifyContent: "flex-end",
    alignItems: "center",
    height: Dimensions.get("window").height,
    width: Dimensions.get("window").width
  },
  cancel: {
    position: "absolute",
    right: 20,
    top: 20,
    backgroundColor: "transparent",
    color: "#FFF",
    fontWeight: "600",
    fontSize: 17
  }
});

class GalleryView extends React.Component {
  static navigationOptions = ({ navigation }) => ({
    title: "Seismic"
  });

  constructor(props) {
    super(props);
    AsyncStorage.getItem("imageUri").then(response => {
      this.setState({
        imageUri: response
      });
    });
  }

  render() {
    return (
      <View>
        <Image source={{ uri: this.state.imageUri }} style={styles.preview} />

        <Text
          style={styles.cancel}
          onPress={() => this.state.setState({ imageData: null })}
        >
          X
        </Text>
        <Button
          title="Map View"
          onPress={() => this.props.navigation.popToTop()}
        />
      </View>
    );
  }
}

export default GalleryView;

第一个提到的示例工作正常,但在尝试使用AsyncStorage时,我在捕获图像并执行navigate()到第二个视图后得到以下错误 .

TypeError:TypeError:null不是对象(评估'this.state.imageUri')此错误位于:在GalleryView(在SceneView.js:9)中的SceneView(在StackViewLayout.js:478)中的RCTView(at在AVTView(在View.js:44)中的RCTView(在View.js:44中)中的View.js:44)在AnimatedComponent中(在screens.native.js:58处)在Screen中(在StackViewCard.js:42处)在Card中在StackViewLayout中的RCTView(在View.js:44)的ScreenContainer(在StackViewLayout.js:401)的RCTView(在View.js:44)中的Container(在StackViewLayout.js:50)中的(在createView上,在StackViewLayout.js:507) (在withOrientation.js:30中)在RCTView(在View.js:44)中的withOrientation(在StackView.js:49中)在TransitionView中的Stacker(在StackView.js:19中)在StackView中(在createNavigator.js:57处)在Navigator中位于LinkContainer(位于routes.js:39)的KeyboardAwareNavigator中的(在createNavigationContainer.js:37处)(在Route.js:39中)在RCTView中的RCTView(at.js:44)中的Routes(at renderApplication.js:34)中(在View.js:44中)在AppContainer中(在ren derApplication.js:33)>此错误位于以下位置:在RCTView(在View.js:44)的RCTView(在View.js中)的Routes(在renderApplication.js:34)中的NavigationContainer(在routes.js:39处) :44)在AppContainer中(在renderApplication.js:33)渲染C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ src \ screens \ GalleryView.js:25:11 proxiedMethod C:\ Users \ msteinbrink \ Safeguard \ seismic- app \ node_modules \ react-proxy \ modules \ createPrototypeProxy.js:44:35 finishClassComponent C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:10563 :21 updateClassComponent C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:10505:4 beginWork C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:11338:8 performUnitOfWork C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-开发 . js:14091:21 workLoop C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:14129:41 renderRoot C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:14226:15 performWorkOnRoot C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:15193:17 performWork C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:15090:24 performSyncWork C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:15047:14 requestWork C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:14925:19 scheduleWork C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:14711:16 Ë nqueueSetState C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:7700:17 setState C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react \ cjs \ react.development.js:372:31发送C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-navigation \ src \ createNavigationContainer.js:342:22 C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-navigation \ src \ getChildNavigation.js:56:33 _callee2 $ C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ src \ screens \ CameraView.js:88:16 tryCatchC:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ @babel \ runtime \ node_modules \ regenerator-runtime \ runtime.js:62:44调用C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ @ babel \ runtime \ node_modules \ regenerator-runtime \ runtime.js:288:30 C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ @babel \ runtime \ node_modules \ regenerator-runtime \ runtime.js:114:28 tryCatch C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ @babel \ runtime \ node_modules \ regenerator-runtime \ runtime.js:62:44调用C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ @babel \ runtime \ node_modules \ regenerator-runtime \ runtime.js:152:28 C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ @babel \ runtime \ node_modules \ regenerator-runtime \ runtime.js:162: 19 tryCallOne C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ promise \ setimmediate \ core.js:37:14 C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ promise \ setimmediate \ core.js :123:25 C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modul es \ react-native \ Libraries \ Core \ Timers \ JSTimers.js:295:23 _callTimer C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Core \ Timers \ JSTimers.js:152 :14 _callImmediatesPass C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Core \ Timers \ JSTimers.js:200:17 callImmediates C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Core \ Timers \ JSTimers.js:464:30 __callImmediates C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ BatchedBridge \ MessageQueue.js:320:6 C :\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ BatchedBridge \ MessageQueue.js:135:6 __guard C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ BatchedBridge \ MessageQueue.js:297:10 flushedQueue C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ BatchedBridge \ MessageQueue.js:134:17 invokeCallbackAndReturnFlushedQueue C:\ Users \ msteinbrink \ Safeguard \地震应用内\ node_modules \反应天然\库\ BatchedBridge \ MessageQueue.js:130:11

如果有人能指出如何正确使用AsyncStorage与React Navigation来渲染以前保存的React Native Camera图像,我将不胜感激 . 你可能会说,我对React Native来说相当新,所以请告诉我,我是否完全错了这个概念 .

提前致谢!

1 回答

  • 0

    感谢Wainages的评论,我做到了 . 我在GalleryView中添加了状态isLoaded,并在异步操作完成之前显示文本“正在加载” .

    import React from "react";
    import {
      AsyncStorage,
      Dimensions,
      StyleSheet,
      Text,
      Button,
      Image,
      View
    } from "react-native";
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        alignItems: "center",
        justifyContent: "center",
        backgroundColor: "#000000"
      },
      preview: {
        flex: 1,
        justifyContent: "flex-end",
        alignItems: "center",
        height: Dimensions.get("window").height,
        width: Dimensions.get("window").width
      },
      cancel: {
        position: "absolute",
        right: 20,
        top: 20,
        backgroundColor: "transparent",
        color: "#FFF",
        fontWeight: "600",
        fontSize: 17
      }
    });
    
    class GalleryView extends React.Component {
      static navigationOptions = ({ navigation }) => ({
        title: "Seismic"
      });
    
      constructor(props) {
        super(props);
        this.state = {
          imageUri: null,
          isLoaded: false
        };
    
        AsyncStorage.getItem("imageUri").then(response => {
          this.setState({
            isLoaded: true,
            imageUri: response
          });
        });
      }
    
      renderImage() {
        return (
          <View>
            <Image source={{ uri: this.state.imageUri }} style={styles.preview} />
            <Text
              style={styles.cancel}
              onPress={() => this.setState({ path: null })}
            >
              X
            </Text>
          </View>
        );
      }
    
      renderLoadingScreen() {
        return (
          <View>
            <Text style={styles.cancel}>Loading</Text>
            <Button
              title="Map View"
              onPress={() => this.props.navigation.popToTop()}
            />
          </View>
        );
      }
    
      render() {
        return (
          <View style={styles.container}>
            {this.state.isLoaded ? this.renderImage() : this.renderLoadingScreen()}
          </View>
        );
      }
    }
    
    export default GalleryView;
    

相关问题