如何通过StackNavigator将ImagePicker媒体源传递到另一导航页面?
嘿,我来帮你搞定这个需求!你现在需要把拍摄或选择的图片、视频从SecondScreen传递到ThirdScreen展示对吧?核心思路是把媒体数据的状态提升到父组件SecondScreen,然后在跳转时通过StackNavigator的参数传递数据,最后在ThirdScreen里接收并展示。咱们一步步修改代码:
步骤1:重构SecondScreen,统一管理媒体状态
把ImagePickerProject和VideoPickerProject里的状态移到父组件SecondScreen,同时给子组件传递回调函数,用于更新父组件的状态:
import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View, PixelRatio, TouchableOpacity, Image, } from 'react-native'; import ImagePicker from 'react-native-image-picker'; import Video from 'react-native-video'; import ThirdScreen from './ThirdScreen'; import Help from './app/components/Help'; const util = require('util'); class SecondScreen extends React.Component { static navigationOptions = { header: null, }; state = { selectedImage: null, // 保存选中的图片 selectedVideo: null // 保存选中的视频 }; // 更新图片的回调 handleImageSelect = (imageSource) => { this.setState({ selectedImage: imageSource }); }; // 更新视频的回调 handleVideoSelect = (videoSource) => { this.setState({ selectedVideo: videoSource }); }; render() { const { navigate } = this.props.navigation; const { selectedImage, selectedVideo } = this.state; return ( <View style={styles.container}> <Help onPress={() => navigate("HelpSecond")} /> {/* 跳转时把选中的媒体数据作为参数传递 */} <TouchableOpacity style={styles.button} onPress={() => navigate("Third", { image: selectedImage, video: selectedVideo })} > <Text>跳转到ThirdScreen查看媒体</Text> </TouchableOpacity> {/* 给子组件传递回调和当前选中的媒体 */} <ImagePickerProject selectedImage={selectedImage} onImageSelect={this.handleImageSelect} /> <VideoPickerProject selectedVideo={selectedVideo} onVideoSelect={this.handleVideoSelect} /> </View> ); } };
步骤2:修改ImagePickerProject组件,去掉内部状态,改用props
让子组件不再自己维护状态,而是通过props接收数据和回调:
class ImagePickerProject extends Component { selectPhotoTapped = () => { const options = { maxWidth: 1000, maxHeight: 1000, storageOptions: { skipBackup: true, } }; ImagePicker.showImagePicker(options, (response) => { console.log('Response = ', response.fileName); if (response.didCancel) { console.log('User cancelled photo picker'); } else if (response.error) { console.log('ImagePicker Error: ', response.error); } else if (response.customButton) { console.log('User tapped custom button: ', response.customButton); } else { let source = { uri: response.uri }; // 调用父组件的回调,传递图片数据 this.props.onImageSelect(source); } }); }; render() { const { selectedImage } = this.props; return ( <View style={styles.Image}> {selectedImage === null ? ( <TouchableOpacity style={styles.button} onPress={this.selectPhotoTapped}> <Text>拍摄/选择图片</Text> </TouchableOpacity> ) : ( <Image resizeMode={'cover'} style={{ width: '100%', height: 400 }} source={selectedImage} /> )} </View> ); } };
步骤3:修改VideoPickerProject组件,同理调整为props驱动
同样去掉内部状态,使用父组件传递的props:
class VideoPickerProject extends Component { selectVideoTapped = () => { const options = { title: 'Video Picker', takePhotoButtonTitle: '拍摄视频...', mediaType: 'video', videoQuality: 'medium', storageOptions: { skipBackup: true } }; ImagePicker.showImagePicker(options, (response) => { console.log('Response = ', response); if (response.didCancel) { console.log('User cancelled video picker'); } else if (response.error) { console.log('ImagePicker Error: ', response.error); } else if (response.customButton) { console.log('User tapped custom button: ', response.customButton); } else { let source = { uri: response.uri }; // 调用父组件的回调,传递视频数据 this.props.onVideoSelect(source); } }); }; // 补充Video组件需要的空事件处理函数(避免报错) loadStart = () => {}; setDuration = () => {}; setTime = () => {}; onEnd = () => {}; videoError = () => {}; onBuffer = () => {}; render() { const { selectedVideo } = this.props; return ( <View style={styles.Image}> {selectedVideo === null ? ( <TouchableOpacity style={styles.button} onPress={this.selectVideoTapped}> <Text>拍摄/选择视频</Text> </TouchableOpacity> ) : ( <Video style={{ width: '100%', height: 400 }} source={selectedVideo} ref={(ref) => { this.player = ref }} rate={1.0} volume={1.0} muted={false} paused={false} resizeMode="cover" repeat={true} playInBackground={false} playWhenInactive={false} ignoreSilentSwitch={"ignore"} progressUpdateInterval={250.0} onLoadStart={this.loadStart} onLoad={this.setDuration} onProgress={this.setTime} onEnd={this.onEnd} onError={this.videoError} onBuffer={this.onBuffer} /> )} </View> ); } };
步骤4:在ThirdScreen.js中接收并展示媒体数据
最后在ThirdScreen里通过route.params(React Navigation 5+)获取传递的参数,然后展示:
import React from 'react'; import { View, Image, StyleSheet, Video } from 'react-native'; class ThirdScreen extends React.Component { // 补充Video需要的空事件函数 loadStart = () => {}; setDuration = () => {}; setTime = () => {}; onEnd = () => {}; videoError = () => {}; onBuffer = () => {}; render() { const { image, video } = this.props.route.params || {}; return ( <View style={styles.container}> {image && ( <Image resizeMode="cover" style={styles.media} source={image} /> )} {video && ( <Video style={styles.media} source={video} rate={1.0} volume={1.0} muted={false} paused={false} resizeMode="cover" repeat={true} onLoadStart={this.loadStart} onLoad={this.setDuration} onProgress={this.setTime} onEnd={this.onEnd} onError={this.videoError} onBuffer={this.onBuffer} /> )} </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, alignItems: 'center', justifyContent: 'center' }, media: { width: '100%', height: 400, marginBottom: 20 } }); export default ThirdScreen;
关键注意点
- 状态提升:把媒体数据的状态从子组件移到父组件,这样父组件才能统一管理并传递给其他页面。
- 参数传递:StackNavigator跳转时,通过第二个参数传递对象格式的参数,ThirdScreen通过
route.params获取。 - 事件处理:Video组件需要绑定一些事件处理函数,即使是空函数也要定义,避免运行时报错。
内容的提问来源于stack exchange,提问作者Katrina Miezite
相关产品推荐
相关产品推荐

