You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过StackNavigator将ImagePicker媒体源传递到另一导航页面?

解决React Native中通过StackNavigator传递图片/视频到ThirdScreen的问题

嘿,我来帮你搞定这个需求!你现在需要把拍摄或选择的图片、视频从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:35:16