React Native:通过AsyncStorage保存图片URI,然后在不同的React Navigation屏幕中重新加载

时间:2018-10-29 14:15:51

标签: image react-native react-navigation asyncstorage react-native-camera

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

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

这是两个视图的代码:

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中(在View.js:44)       在RCTView中(在View.js:44)       在RCTView中(在View.js:44)       在AnimatedComponent中(在screens.native.js:58处)       在屏幕上(在StackViewCard.js:42上)       在Card中(在createPointerEventsContainer.js:26处)       在容器中(位于StackViewLayout.js:507)       在RCTView中(在View.js:44)       在ScreenContainer中(在StackViewLayout.js:401处)       在RCTView中(在View.js:44)       在StackViewLayout中(位于withOrientation.js:30)       在withOrientation中(在StackView.js:49处)       在RCTView中(在View.js:44)       在Transitioner中(位于StackView.js:19)       在StackView中(位于createNavigator.js:57)       在导航器中(位于createKeyboardAwareNavigator.js:11处)       在KeyboardAwareNavigator中(位于createNavigationContainer.js:376)       在NavigationContainer中(在routes.js:39处)       在路由中(在renderApplication.js:34处)       在RCTView中(在View.js:44)       在RCTView中(在View.js:44)       在AppContainer中(在renderApplication.js:33处)   >

     
    

此错误位于:         在NavigationContainer中(在routes.js:39处)         在路由中(在renderApplication.js:34处)         在RCTView中(在View.js:44)         在RCTView中(在View.js:44)         在AppContainer中(在renderApplication.js:33处)呈现         C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ src \ screens \ GalleryView.js:25:11     代理方法         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     开始工作         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-dev.js:14091:21     工作循环         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     计划工作         C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ react-native \ Libraries \ Renderer \ oss \ ReactNativeRenderer-dev.js:14711:16     enqueueSetState         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     试着抓         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:288:30              C:\ Users \ msteinbrink \ Safeguard \ seismic-app \ node_modules \ @babel \ runtime \ node_modules \ regenerator-runtime \ runtime.js:114:28     试着抓         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_modules \ 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     立即致电         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     __守护         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 \ seismic-app \ node_modules \ react-native \ Libraries \ BatchedBridge \ MessageQueue.js:130:11

  

如果有人能指出如何正确地将AsyncStorage与React Navigation一起使用,以从React Native Camera渲染以前保存的图像,我将不胜感激。您可能会说,我对React Native还是很陌生,所以请告诉我我是否完全错误地理解了这个概念。

谢谢!

1 个答案:

答案 0 :(得分:0)

感谢Wainages评论,我成功了。在异步操作完成之前,我在GalleryView中添加了isLoaded状态,并仅显示文本“ Loading”。

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;