【问题标题】:React Native: Saving image URI via AsyncStorage and reloading in different React Navigation screenReact Native:通过 AsyncStorage 保存图像 URI 并在不同的 React Navigation 屏幕中重新加载
【发布时间】:2019-04-02 11:57:40
【问题描述】:

我目前正在尝试将 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) 在卡片中(在 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) 在过渡器中(在 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 完成类组件 C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:10563:21 更新类组件 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 执行工作单元 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 渲染根 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 执行工作 C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:15090:24 执行同步工作 C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:15047:14 请求工作 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 设置状态 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 尝试CallOne 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 刷新队列 C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:134:17 调用CallbackAndReturnFlushedQueue C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:130:11

如果有人能指出如何正确使用 AsyncStorage 和 React Navigation 来渲染以前从 React Native Camera 保存的图像,我将不胜感激。您可能会说,我对 React Native 还很陌生,所以请告诉我我的概念是完全错误的还是什么。

提前致谢!

【问题讨论】:

  • AsyncStorage 是异步的。将isLoaded 标志添加到您的州。异步部分完成后设置为 true。渲染加载屏幕,直到该标志为真

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


【解决方案1】:

感谢 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;

【讨论】:

    猜你喜欢
    • 2021-07-08
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多