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

React Native条件渲染下Modal关闭前短暂闪烁问题解决咨询

解决React Native Modal关闭时的闪烁问题

问题根源

你在每个条件渲染的下拉区域里都嵌套了一个AddressModal组件,这意味着当条件渲染触发(比如选中Division后显示District),页面中会同时存在多个AddressModal实例。这些实例共享同一个isModalVisible状态,当关闭Modal时,多个实例的渲染状态同步变化,导致视觉上的闪烁。

核心修复方案

将AddressModal从各个下拉组件中移除,只在整个SignupPresentAddress组件的根层级渲染一次。这样始终只有一个Modal实例,避免多实例状态同步冲突。

修改后的SignupPresentAddress代码

import { View, Text, TextInput, Pressable, Image, Modal } from 'react-native'
import React, { useEffect, useState } from 'react'

import { useGeolocationStore, useUserStore } from '../app/stores/store.js'
import GradientButton from '../components/GradientButton'

import AddressModal from '../components/AddressModal'

const SignupPresentAddress = ({ setCurrentComponent }) => {
    const { user, setSelectedAddressType, setSelectedAddressCategory } = useUserStore()

    const [isModalVisible, setIsModalVisible] = useState(false)

    const [isDivisionSelected, setIsDivisionSelected] = useState(false)
    const [isDistrictSelected, setIsDistrictSelected] = useState(false)
    const [isUpazilaSelected, setIsUpazilaSelected] = useState(false)

    useEffect(() => {
        setIsDivisionSelected(!!(user.presentAddress?.division))
        setIsDistrictSelected(!!(user.presentAddress?.district))
        setIsUpazilaSelected(!!(user.presentAddress?.upazila))
    }, [user.presentAddress])

    const handlePrevButtonPress = () => {
        setCurrentComponent('m-verification')
    }
    const handleNextButtonPress = () => {
        setCurrentComponent('permanent-address')
    }

    const handlePressDropdown = (category) => {
        setSelectedAddressCategory(category)
        setIsModalVisible(true)
    }

    useEffect(() => {
        setSelectedAddressType('present')
    }, [])

    return (
        <>
            <Text className='mt-4 text-2xl text-center text-white'>Present Address</Text>
            <View className='w-full max-w-[360px] mt-4 gap-y-4'>

                <View>
                    <Text className='text-white text-lg'>Division</Text>
                    <Pressable
                        onPress={() => handlePressDropdown('divisions')}
                    >
                        <View className='relative'>
                            <TextInput
                                className='bg-white rounded-full text-lg mt-2 px-5 py-3 p-4'
                                value={user?.presentAddress?.division?.name}
                                editable={false}
                            />
                            <Image
                                className='absolute w-10 h-10 right-3 top-3'
                                source={require('../assets/icons/expand-arrow-down.png')}
                            />
                        </View>
                    </Pressable>
                </View>

                {isDivisionSelected && (
                    <View>
                        <Text className='text-white text-lg'>District</Text>
                        <Pressable
                            onPress={() => handlePressDropdown('districts')}
                        >
                            <View className='relative'>
                                <TextInput
                                    className='bg-white rounded-full text-lg mt-2 px-5 py-3 p-4'
                                    value={user?.presentAddress?.district?.name}
                                    editable={false}
                                />
                                <Image
                                    className='absolute w-10 h-10 right-3 top-3'
                                    source={require('../assets/icons/expand-arrow-down.png')}
                                />
                            </View>
                        </Pressable>
                    </View>
                )}

                {isDistrictSelected && (
                    <View>
                        <Text className='text-white text-lg'>Sub-district</Text>
                        <Pressable
                            onPress={() => handlePressDropdown('upazilas')}
                        >
                            <View className='relative'>
                                <TextInput
                                    className='bg-white rounded-full text-lg mt-2 px-5 py-3 p-4'
                                    value={user?.presentAddress?.upazila?.name}
                                    editable={false}
                                />
                                <Image
                                    className='absolute w-10 h-10 right-3 top-3'
                                    source={require('../assets/icons/expand-arrow-down.png')}
                                />
                            </View>
                        </Pressable>
                    </View>
                )}

                {isUpazilaSelected && (
                    <View>
                        <Text className='text-white text-lg'>Union</Text>
                        <Pressable
                            onPress={() => handlePressDropdown('unions')}
                        >
                            <View className='relative'>
                                <TextInput
                                    className='bg-white rounded-full text-lg mt-2 px-5 py-3 p-4'
                                    value={user?.presentAddress?.union?.name}
                                    editable={false}
                                />
                                <Image
                                    className='absolute w-10 h-10 right-3 top-3'
                                    source={require('../assets/icons/expand-arrow-down.png')}
                                />
                            </View>
                        </Pressable>
                    </View>
                )}

                <View>
                    <Text className='text-white text-lg'>Address Line 1 (e.g. House / Road / Village)</Text>
                    <TextInput
                        className='bg-white rounded-full text-lg mt-2 px-5 py-3 p-4'
                        placeholder='Address Line 1 (e.g. House / Road / Village)'
                        numberOfLines={1}
                    />
                </View>

                <View>
                    <Text className='text-white text-lg'>Address Line 2 (e.g. Area / Post Office)</Text>
                    <TextInput
                        className='bg-white rounded-full text-lg mt-2 px-5 py-3 p-4'
                        placeholder='Address Line 2 (e.g. Area / Post Office)'
                        numberOfLines={1}
                    />
                </View>

                <View className='flex-row w-full justify-between mt-4'>
                    <GradientButton
                        handlePress={handlePrevButtonPress}
                    >
                        <Text className='text-xl text-dark1 text-center'>Previous</Text>
                    </GradientButton>
                    <GradientButton
                        handlePress={handleNextButtonPress}
                    >
                        <Text className='text-xl text-dark1 text-center'>Next</Text>
                    </GradientButton>
                </View>
            </View>
            {/* 仅渲染一次AddressModal */}
            <AddressModal
                isModalVisible={isModalVisible}
                setIsModalVisible={setIsModalVisible}
            />
        </>
    )
}

export default SignupPresentAddress

额外优化建议

  1. 简化状态判断:用!!快速将可选值转为布尔类型,精简useEffect内的逻辑
  2. 明确Modal触发逻辑:修改handlePressDropdown,先设置分类再打开Modal,避免Modal显示时数据未准备完全

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 09:42:04