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

如何在react-native-calendars中实现年份选择功能?

解决react-native-calendars年份选择后需关闭重开才生效的问题

问题根源在于两处:冗余的useEffect引发无效渲染循环,以及react-native-calendars的Calendar组件未触发即时视图更新。

修复步骤:

  1. 移除无效的useEffect
    你代码中这段useEffect完全多余,还会导致无限渲染循环,直接删除:

    useEffect(() => {
        setCurrentYear(prevYear => {
            return prevYear
        })
    }, [currentYear])
    
  2. 给Calendar组件添加key属性
    给NativeCalendar添加key={currentYear},当currentYear变化时,React会重新挂载组件,立即切换到选中的年份。

修改后的完整代码:

import { theme } from "@/Common/theme"
import React, { useState } from "react"
import { Modal, Text, TouchableOpacity, View } from "react-native"
import { Calendar as NativeCalendar } from "react-native-calendars"
import ModalSelector from "react-native-modal-selector"
import { useCalendar } from "./useCalendar"

export interface CalendarProps {
    visible: boolean
    onClose: () => void
    onChange: (value: string) => void
    value?: string
}

export const Calendar = (props: CalendarProps): JSX.Element => {
    const { visible, styles, onClose, markedDate, onMarkedDateChange, rest } =
        useCalendar(props)
    const [selectedYear, setSelectedYear] = useState("")
    const [currentYear, setCurrentYear] = useState(
        new Date().getFullYear().toString()
    )

    const renderYearSelector = () => {
        const years = Array.from({ length: 100 }, (_, index) => {
            const currentYear = new Date().getFullYear()
            return { label: `${currentYear - index}`, key: index.toString() }
        })

        return (
            <ModalSelector
                data={years}
                initValue="Seleccione el año"
                onChange={option => {
                    setSelectedYear(option.label)
                    setCurrentYear(option.label)
                }}
            />
        )
    }

    return (
        <Modal visible={visible} animationType="fade" transparent {...rest}>
            <View style={styles.viewCalendar}>
                <View style={styles.calendarContainer}>
                    <View style={styles.calendarHeader}>
                        <Text style={{ color: theme.colors.WHITE }}>
                            Seleccionar fecha
                        </Text>
                        <Text style={styles.selectDate}>
                            {markedDate && markedDate !== ""
                                ? new Date(markedDate).toLocaleDateString(
                                      "es-CO",
                                      {
                                          day: "2-digit",
                                          weekday: "short",
                                          month: "short",
                                      }
                                  )
                                : new Date().toLocaleDateString("es-CO", {
                                      day: "2-digit",
                                      weekday: "short",
                                      month: "short",
                                  })}
                        </Text>
                    </View>
                    {renderYearSelector()}
                    <NativeCalendar
                        key={currentYear}
                        theme={{
                            calendarBackground: "transparent",
                        }}
                        onDayPress={(date: { dateString: string }) =>
                            onMarkedDateChange(date.dateString)
                        }
                        markedDates={{
                            [markedDate]: {
                                selected: true,
                                color: theme.colors.SECONDARY,
                            },
                        }}
                        current={`${currentYear}-01-01`}
                    />
                    <View style={styles.buttonscontainer}>
                        <TouchableOpacity onPress={onClose}>
                            <Text style={styles.cancel}>CANCELAR</Text>
                        </TouchableOpacity>
                        <TouchableOpacity onPress={onClose}>
                            <Text style={styles.accept}>ACEPTAR</Text>
                        </TouchableOpacity>
                    </View>
                </View>
            </View>
        </Modal>
    )
}

原理说明:

react-native-calendars的Calendar组件内部未监听current属性变化来触发视图更新,通过添加key={currentYear},当年份改变时,React会识别为新组件并重新渲染,直接加载对应年份的日历视图,无需关闭重开Modal即可即时生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:17:04