我目前正在尝试将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还是很陌生,所以请告诉我我是否完全错误地理解了这个概念。
谢谢!
答案 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;