You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React Native嵌套Modal无法显示问题排查与解决

解决React Native中嵌套Modal无法显示的问题

嘿,我瞅了瞅你的代码,发现问题出在几个关键地方,尤其是Modal的渲染逻辑上——你不能在按钮的点击事件里直接写Modal的JSX,得用状态来控制它的显示!咱们一步步来修复:

核心问题分析

  • 错误的Modal渲染方式:你在onPress的条件判断里直接返回了Modal组件,但React的组件只能在组件的返回值(函数组件的render区域)里渲染,事件处理函数里的JSX根本不会被渲染到页面上。
  • 状态控制逻辑混乱:第二个Modal的visible属性用了!visible,但你没有在点击事件里更新visible状态,自然不会触发Modal的显示。
  • TextInput的value绑定错误:你写的value={textInput},但并没有定义textInput变量,应该绑定你声明的number状态。

修复步骤及完整代码

咱们把这些问题逐个修复,下面是修改后的完整代码:

import React, { useState } from 'react';
import { View, Modal, TextInput, TouchableOpacity, Text, Image } from 'react-native';
import { Button } from 'react-native-paper';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';

const styles = {
  mainOuterComponent: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.5)',
    justifyContent: 'center',
    alignItems: 'center',
  },
  mainContainer: {
    backgroundColor: 'white',
    borderRadius: 16,
    padding: 20,
    width: '80%',
    elevation: 10,
  },
  topPart: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 15,
  },
  alertIconStyle: {
    width: 30,
    height: 30,
    marginRight: 10,
  },
  alertTitleTextStyle: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  middlePart: {
    marginBottom: 20,
  },
  alertMessageTextStyle: {
    fontSize: 16,
  },
  bottomPart: {
    justifyContent: 'flex-end',
    alignItems: 'flex-end',
  },
  alertMessageButtonStyle: {
    paddingHorizontal: 20,
    paddingVertical: 8,
  },
  alertMessageButtonTextStyle: {
    color: '#006aff',
    fontSize: 16,
    fontWeight: 'bold',
  },
};

function Search({ navigation }) {
  const [number, setNumber] = useState('');
  // 单独用一个状态控制提示Modal的显示/隐藏
  const [alertVisible, setAlertVisible] = useState(false);

  const handleSearchPress = () => {
    if (number.trim() === '') {
      // 更新状态,触发提示Modal显示
      setAlertVisible(true);
    } else {
      console.log('Do Nothing!');
    }
  };

  return (
    <View style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.5)' }}>
      {/* 主搜索Modal */}
      <Modal
        visible={true}
        transparent={true}
        animationType="fade"
      >
        <View
          style={{
            margin: 50,
            padding: 10,
            borderRadius: 35,
            height: 'auto',
            flexDirection: 'column',
            justifyContent: 'center',
            shadowColor: '#000',
            shadowOffset: { width: 0, height: 12 },
            shadowOpacity: 0.58,
            shadowRadius: 16.0,
            elevation: 24,
            backgroundColor: '#fafcff',
          }}
        >
          <TextInput
            label="Enter a phone number"
            value={number}
            keyboardType="numeric"
            maxLength={12}
            mode="outlined"
            dense={true}
            theme={{ colors: { primary: '#00aaff' } }}
            onChangeText={(text) => setNumber(text)}
          />
          <Button
            mode="contained"
            theme={{ colors: { primary: '#006aff' } }}
            style={{
              margin: 70,
              marginTop: 10,
              padding: 2,
              shadowColor: '#000',
              shadowOffset: { width: 0, height: 5 },
              shadowOpacity: 0.34,
              shadowRadius: 6.27,
              justifyContent: 'center',
              elevation: 18,
              borderRadius: 18,
            }}
            onPress={handleSearchPress}
          >
            <Text style={{ fontSize: 25, color: 'white', textAlign: 'center' }}>
              <MaterialCommunityIcons
                name="database-search"
                size={40}
                color="yellow"
                style={{ paddingRight: 5, margin: 5 }}
              />
              Search
            </Text>
          </Button>
        </View>
      </Modal>

      {/* 提示输入为空的Modal,放在组件返回值里,用状态控制显示 */}
      <Modal
        visible={alertVisible}
        transparent={true}
        animationType="fade"
      >
        <View style={styles.mainOuterComponent}>
          <View style={styles.mainContainer}>
            <View style={styles.topPart}>
              <Image
                source={require('../images/ic_notification.png')}
                resizeMode={'contain'}
                style={styles.alertIconStyle}
              />
              <Text style={styles.alertTitleTextStyle}>提示</Text>
            </View>
            <View style={styles.middlePart}>
              <Text style={styles.alertMessageTextStyle}>请输入电话号码</Text>
            </View>
            <View style={styles.bottomPart}>
              <TouchableOpacity
                onPress={() => setAlertVisible(false)}
                style={styles.alertMessageButtonStyle}
              >
                <Text style={styles.alertMessageButtonTextStyle}>Okay</Text>
              </TouchableOpacity>
            </View>
          </View>
        </View>
      </Modal>
    </View>
  );
}

export default Search;

关键改动说明

  1. 状态拆分:把控制提示Modal的状态单独拆成alertVisible,避免和其他状态混淆,逻辑更清晰。
  2. 事件处理抽离:把按钮点击逻辑抽成handleSearchPress函数,在里面通过setAlertVisible(true)来触发提示Modal的显示,而不是直接写JSX。
  3. 修正TextInput绑定:把value={textInput}改成value={number},和你的状态对应上。
  4. 调整主Modal的View样式:给主Modal里的View加上backgroundColor: '#fafcff',不然会透明看不到内容;把height: 40改成height: 'auto',避免输入框和按钮被截断。
  5. 添加关闭提示Modal的逻辑:在Okay按钮的点击事件里设置setAlertVisible(false),让用户可以关闭提示框。

这样修改后,当用户输入为空点击Search按钮时,提示Modal就能正常显示啦!

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

火山引擎 最新活动