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

React Native三屏切换时报props.screen handler() is not a function如何解决

问题修复说明

报错原因

  • props传递不全:你给每个子页面仅传入了1个切换处理函数,但Modal内需要调用3个切换函数,未传入的函数不存在,自然会报props.screen handler() is not a function错误
  • 组件名拼写错误:App.js中初始content赋值用了小写的<screen1 />,React 组件名必须大写开头,会导致组件渲染异常
  • 子组件缺少状态定义:你提供的Screen1代码中直接使用了modalVisible和setModalVisible,但没有通过useState声明该状态,运行时也会报错
  • 状态逻辑冗余:用3个布尔值管理当前激活页面,维护成本高,容易写错判断逻辑

Modal复用方案合理性

多页面复用主题切换Modal的需求是合理的,但你当前每个页面都重写一遍Modal代码的实现方式不合理,重复代码太多,后续修改要同步改3份,建议将Modal抽为独立公共组件,或者直接放在App父组件中全局管理,只需维护1份代码即可。

修复后代码示例

1. 优化后的App.js

import React, { useState } from "react";
import { StyleSheet, View } from "react-native";

import Screen1 from "./screens/CalcScreen";
import Screen2 from "./screens/Screen1";
import Screen3 from "./screens/Screen2";
// 引入抽离的公共Modal
import ThemeModal from "./components/ThemeModal";

export default function App() {
  // 用单个状态管理当前激活的主题页面,可选值:dark/white/pink
  const [currentTheme, setCurrentTheme] = useState("dark");
  // 全局控制Modal显隐,不用每个页面单独维护
  const [modalVisible, setModalVisible] = useState(false);

  // 切换主题的统一处理函数
  const changeTheme = (theme) => {
    setCurrentTheme(theme);
    // 切换后自动关闭Modal
    setModalVisible(false);
  };

  // 根据当前主题渲染对应页面
  let renderContent;
  if (currentTheme === "dark") {
    renderContent = <Screen1 openModal={() => setModalVisible(true)} />;
  } else if (currentTheme === "white") {
    renderContent = <Screen2 openModal={() => setModalVisible(true)} />;
  } else if (currentTheme === "pink") {
    renderContent = <Screen3 openModal={() => setModalVisible(true)} />;
  }

  return (
    <View style={styles.container}>
      {renderContent}
      {/* 全局挂载主题切换Modal */}
      <ThemeModal 
        visible={modalVisible}
        onClose={() => setModalVisible(false)}
        onChangeTheme={changeTheme}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#374351",
  },
});

2. 抽离的公共ThemeModal组件(新建components/ThemeModal.js)

import React from "react";
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  Modal,
  Pressable,
} from "react-native";

// 所有配置通过props传入,完全复用
const ThemeModal = (props) => {
  return (
    <Modal
      animationType="slide"
      transparent={true}
      visible={props.visible}
      onRequestClose={props.onClose}
    >
      <View style={styles.centeredView}>
        <View style={styles.modalView}>
          <View style={styles.button}></View>
          <Text style={styles.modalText}>Themes</Text>

          <TouchableOpacity
            style={styles.darkTheme}
            onPress={() => props.onChangeTheme("dark")}
          >
            <Text>Dark</Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={styles.whiteTheme}
            onPress={() => props.onChangeTheme("white")}
          >
            <Text>White</Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={styles.pinkTheme}
            onPress={() => props.onChangeTheme("pink")}
          >
            <Text>Pink</Text>
          </TouchableOpacity>
          <Pressable
            style={[styles.buttonClose]}
            onPress={props.onClose}
          >
            <Text style={styles.textStyle}>X</Text>
          </Pressable>
        </View>
      </View>
    </Modal>
  )
}

const styles = StyleSheet.create({
  centeredView: {
    marginStart: 15,
    justifyContent: "center",
    alignItems: "center",
  },
  modalView: {
    marginTop: 200,
    backgroundColor: "rgba(255,255,255,0.5)",
    borderRadius: 20,
    padding: 20,
    alignItems: "center",
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.5,
    shadowRadius: 4,
    elevation: 5,
  },
  button: {
    borderRadius: 15,
    padding: 10,
    elevation: 2,
    justifyContent: "center",
    alignItems: "center",
    marginTop: 20,
  },
  buttonClose: {
    backgroundColor: "rgba(1,1,1,1)",
    height: 40,
    width: 40,
    borderRadius: 50,
    elevation: 2,
    justifyContent: "center",
    alignItems: "center",
    marginTop: 20,
  },
  textStyle: {
    color: "white",
    textAlign: "center",
  },
  modalText: {
    marginBottom: 10,
    textAlign: "center",
  },
  darkTheme: {
    padding: 10,
    marginVertical: 5,
    backgroundColor: "#333",
    width: 100,
    alignItems: "center",
    borderRadius: 8,
  },
  whiteTheme: {
    padding: 10,
    marginVertical: 5,
    backgroundColor: "#fff",
    width: 100,
    alignItems: "center",
    borderRadius: 8,
  },
  pinkTheme: {
    padding: 10,
    marginVertical: 5,
    backgroundColor: "pink",
    width: 100,
    alignItems: "center",
    borderRadius: 8,
  },
});

export default ThemeModal;

3. 简化后的子页面(以Screen1为例,另外两个页面同理修改)

import React from "react";
import {
  StyleSheet,
  View,
  Pressable,
  Text,
} from "react-native";

const Screen1 = (props) => {
  return (
    <View style={styles.screen}>
      {/* 打开Modal的按钮,调用父组件传入的openModal方法 */}
      <Pressable
        style={[styles.button, styles.buttonOpen]}
        onPress={props.openModal}
      >
        <Text style={styles.openText}>{">"}</Text>
      </Pressable>
      {/* 你页面的其他业务内容 */}
    </View>
  )
}
const styles = StyleSheet.create({
  screen: {
    flex: 1,
    backgroundColor: "#fafcff",
  },
  button: {
    borderRadius: 15,
    padding: 10,
    elevation: 2,
    justifyContent: "center",
    alignItems: "center",
    marginTop: 20,
  },
  buttonOpen: {
    backgroundColor: "rgba(1,143,132,0.6)",
    position: "absolute",
    marginTop: 45,
    marginStart: -25,
    elevation: 2,
    height: 70,
    width: 40,
  },
  openText: {
    fontSize: 25,
    fontWeight: "bold",
    color: "white",
    textAlign: "right",
  },
});
export default Screen1;

内容的提问来源于stack exchange,提问作者user10078002

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:15:04