React Native: сохранение URI изображения через AsyncStorage и перезагрузка в другом окне навигации React - PullRequest
0 голосов
/ 29 октября 2018

В настоящее время я пытаюсь объединить React Native Camera пример с React Navigation v2 и хочу сделать снимок в первом виде (называемый CameraView), сохранить указанное изображение в AsyncStorage, перейти ко второму просмотреть (называется GalleryView) и визуализировать это изображение из AsyncStorage в тег изображения.

Я использую RN 0.57.1, RN-Camera 1.3.1, React Navigation 2.18.0 на компьютере под управлением Windows 10, эмулируя телефон Android с версией Android 8.0.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) в Transitioner (в StackView.js: 19) в StackView (в createNavigator.js: 57) в навигаторе (в createKeyboardAwareNavigator.js: 11) в KeyboardAwareNavigator (в createNavigationContainer.js: 376) в NavigationContainer (по адресу route.js: 39) в маршрутах (в renderApplication.js: 34) в RCTView (на View.js: 44) в RCTView (на View.js: 44) в AppContainer (в renderApplication.js: 33) >

Эта ошибка находится по адресу: в NavigationContainer (по адресу route.js: 39) в маршрутах (в renderApplication.js: 34) в RCTView (на View.js: 44) в RCTView (на View.js: 44) в AppContainer (в renderApplication.js: 33) рендер C: \ Users \ msteinbrink \ Safeguard \ сейсмически приложение \ SRC \ экраны \ GalleryView.js: 25: 11 proxiedMethod C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагирующий-прокси \ Modules \ createPrototypeProxy.js: 44: 35 finishClassComponent C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 10563: 21 updateClassComponent C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 10505: 4 BeginWork C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 11338: 8 performUnitOfWork C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 14091: 21 workLoop C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 14129: 41 renderRoot C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 14226: 15 performWorkOnRoot C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 15193: 17 performWork C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 15090: 24 performSyncWork C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 15047: 14 requestWorkC: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 14925: 19 scheduleWork C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 14711: 16 enqueueSetState C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать чужеродных \ Библиотеки \ Renderer \ ОСС \ ReactNativeRenderer-dev.js: 7700: 17 SetState C: \ Users \ msteinbrink \ Safeguard \ сейсмическую-приложение \ node_modules \ реагировать \ CJS \ react.development.js: 372: 31 отправка C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать-навигация \ SRC \ createNavigationContainer.js: 342: 22 C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать-навигацию \ SRC \ getChildNavigation.js: 56: 33 _callee2 $ C: \ Users \ msteinbrink \ Safeguard \ сейсмически приложение \ SRC \ экраны \ CameraView.js: 88: 16 попробуй поймать C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ @babel \ среда \ node_modules \ регенератор-среда выполнение \ runtime.js: 62: 44 взывать C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ @babel \ среда \ node_modules \ регенератор-среда выполнение \ runtime.js: 288: 30 C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ @babel \ среда \ node_modules \ регенератор-среда выполнение \ runtime.js: 114: 28 попробуй поймать C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ @babel \ среда \ node_modules \ регенератор-среда выполнение \ runtime.js: 62: 44 взывать C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ @babel \ среда \ node_modules \ регенератор-среда выполнение \ runtime.js: 152: 28 C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ @babel \ среда \ node_modules \ регенератор-среда выполнение \ runtime.js: 162: 19 tryCallOne C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ обещание \ setimmediate \ core.js: 37: 14 C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ обещание \ setimmediate \ core.js: 123: 25 C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать родную \ Библиотека \ Основной \ Таймеры \ JSTimers.js: 295: 23 _callTimer C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать родную \ Библиотека \ Основной \ Таймеры \ JSTimers.js: 152: 14 _callImmediatesPass C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать родную \ Библиотека \ Основной \ Таймеры \ JSTimers.js: 200: 17 callImmediates C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать родную \ Библиотека \ Основной \ Таймеры \ JSTimers.js: 464: 30 __callImmediates C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ BatchedBridge \ MessageQueue.js: 320: 6 C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ BatchedBridge \ MessageQueue.js: 135: 6 __guard C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ BatchedBridge \ MessageQueue.js: 297: 10 flushedQueue C: \ Users \ msteinbrink \ Safeguard \ сейсмического-приложение \ node_modules \ реагировать чужеродные \ Библиотеки \ 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 голосов
/ 30 октября 2018

Благодаря комментарию Wainages, я заставил его работать. Я добавил состояние isLoaded в GalleryView и покажу только текст «Загрузка» до выполнения асинхронной операции.

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;
...