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

React Native Agenda组件添加新事项的实现方案求助

解决Agenda组件无法渲染自定义事件的问题

react-native-calendars的Agenda组件对items属性的格式有严格要求,你的代码存在格式不匹配、状态管理混乱的问题,以下是具体修正方案:


一、明确Agenda的items正确格式

Agenda要求items是一个键为日期字符串(YYYY-MM-DD格式),值为对应日期事件数组的对象,示例:

{
  '2022-07-26': [
    { title: '测试事件', description: '这是测试描述' },
    { title: '第二个事件', description: '另一个事件' }
  ],
  '2022-07-27': [
    { title: '明天的事件', description: '明天要做的事' }
  ]
}

二、代码修正细节

1. 重构状态定义

替换零散的状态,用统一的agendaItems存储所有日程数据,单独管理输入框状态:

const Calendario = () => {
  const [modalVisible, setModalVisible] = useState(false);
  // 存储符合Agenda格式的所有日程
  const [agendaItems, setAgendaItems] = useState({});
  // 输入框单独状态
  const [eventTitle, setEventTitle] = useState('');
  const [eventDesc, setEventDesc] = useState('');
  const [dateSelected, setDateSelected] = useState('');
  const [refreshCalender, setRefreshCalender] = useState(false);
  const [isDatePickerVisible, setDatePickerVisibility] = useState(false);

  // ...其他函数保持不变
}

2. 修复日期格式转换

将DateTimePicker返回的Date对象转为YYYY-MM-DD字符串:

const handleConfirm = (date) => {
  const formattedDate = date.toISOString().split('T')[0];
  setDateSelected(formattedDate);
  hideDatePicker();
};

3. 修正Modal提交逻辑

点击确认按钮时,将新事件合并到现有日程数据中:

<TouchableOpacity
  style={[styles.button2, styles.buttonClose2]}
  onPress={() => {
    if (!eventTitle || !dateSelected) {
      Alert.alert('提示', '请填写标题并选择日期');
      return;
    }
    const newEvent = { title: eventTitle, description: eventDesc };
    // 更新日程:已有日期则追加事件,无则新建数组
    setAgendaItems(prev => {
      const currentEvents = prev[dateSelected] || [];
      return {
        ...prev,
        [dateSelected]: [...currentEvents, newEvent]
      };
    });
    // 清空输入框
    setEventTitle('');
    setEventDesc('');
    setModalVisible(false);
  }}>

4. 绑定正确的items到Agenda

将Agenda组件的items属性改为agendaItems:

<Agenda
  items={agendaItems}
  renderEmptyDate={() => <View />}
  renderEmptyData={() => <View />}
  selected={new Date()}
  minDate={null}
  renderItem={renderItem}
  markingType="custom"
  refreshing={refreshCalender}
/>

三、完整修正后的代码

import React, { useState } from 'react'
import { StyleSheet, View, Text, TouchableOpacity, Modal, TextInput, Alert } from 'react-native'
import { LocaleConfig, Agenda } from 'react-native-calendars'
import DateTimePicker from 'react-native-modal-datetime-picker';

import { Feather } from '@expo/vector-icons'; 
import { Ionicons } from '@expo/vector-icons'; 
import { Fontisto } from '@expo/vector-icons';

LocaleConfig.locales['tr'] = {
  monthNames: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio" ,"Junho" ,"Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
  monthNamesShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
  today: "Hoje",
  dayNames: ["Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"],
  dayNamesShort: ["Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"]
}

LocaleConfig.defaultLocale = "tr"

const Calendario = () => {
  const [modalVisible, setModalVisible] = useState(false);
  const [agendaItems, setAgendaItems] = useState({});
  const [eventTitle, setEventTitle] = useState('');
  const [eventDesc, setEventDesc] = useState('');
  const [dateSelected, setDateSelected] = useState('');
  const [refreshCalender, setRefreshCalender] = useState(false);
  const [isDatePickerVisible, setDatePickerVisibility] = useState(false);

  const renderItem = (item) => {
    return(
      <View style={styles.itemContainer}>
        <Text>{item.title}</Text>
        <Text>{item.description}</Text>
      </View>
    )
  }

  const showDatePicker = () => {
    setDatePickerVisibility(true);
  };

  const hideDatePicker = () => {
    setDatePickerVisibility(false);
  };

  const handleConfirm = (date) => {
    const formattedDate = date.toISOString().split('T')[0];
    setDateSelected(formattedDate);
    hideDatePicker();
  };

  return (
    <>
      <Agenda
        items={agendaItems}
        renderEmptyDate={() => <View />}
        renderEmptyData={() => <View />}
        selected={new Date()}
        minDate={null}
        renderItem={renderItem}
        markingType="custom"
        refreshing={refreshCalender}
      />
      <View>
        <Modal
          animationType="slide"
          transparent={true}
          visible={modalVisible}
          onRequestClose={() => {
            Alert.alert('Modal has been closed.');
            setModalVisible(!modalVisible);
          }}>
          <View style={styles.centeredView}>
            <View style={styles.modalView}>
              <Text style={styles.modalText}>Adicione um horário</Text>

              <TextInput 
                placeholder='Título'
                value={eventTitle}
                onChangeText={setEventTitle}
                style={styles.input}
              />

              <TextInput 
                placeholder='Descrição'
                value={eventDesc}
                onChangeText={setEventDesc}
                style={styles.input}
              />

              <TouchableOpacity
                style={styles.btnDatePicker}
                onPress={showDatePicker}
              >
                <Text>Selecionar data</Text>
                <Fontisto name="date" size={20} color="#fff" style={{ margin: 10 }} />
              </TouchableOpacity>

              <DateTimePicker
                mode='date'
                minimumDate={null}
                isVisible={isDatePickerVisible}
                onConfirm={handleConfirm}
                onCancel={hideDatePicker}
              />

              <TouchableOpacity
                style={[styles.button2, styles.buttonClose2]}
                onPress={() => {
                  if (!eventTitle || !dateSelected) {
                    Alert.alert('提示', '请填写标题并选择日期');
                    return;
                  }
                  const newEvent = { title: eventTitle, description: eventDesc };
                  setAgendaItems(prev => {
                    const currentEvents = prev[dateSelected] || [];
                    return {
                      ...prev,
                      [dateSelected]: [...currentEvents, newEvent]
                    };
                  });
                  setEventTitle('');
                  setEventDesc('');
                  setModalVisible(false);
                }}>
                <Text style={styles.textStyle}>
                  <Ionicons name="checkmark-sharp" size={24} color="black" />
                </Text>
              </TouchableOpacity>
              
              <TouchableOpacity
                style={[styles.button, styles.buttonClose]}
                onPress={() => setModalVisible(!modalVisible)}>
                <Text style={styles.textStyle}>
                  <Feather name="x-circle" size={24} color="black" />
                </Text>
              </TouchableOpacity>

            </View>
          </View>
        </Modal>

        <TouchableOpacity style={styles.btn}
          onPress={() => setModalVisible(true)}
        >
          <Ionicons name={'add-outline'} size={30} color={'black'}/>
        </TouchableOpacity>
      </View>
    </>
  )
}

export default Calendario

const styles = StyleSheet.create({
  itemContainer: {
    backgroundColor: "#fff",
    margin: 5,
    borderRadius: 15,
    justifyContent: "center",
    alignItems: "center",
    flex: 1,
  },
  centeredView: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    marginTop: 22,
  },
  modalView: {
    margin: 20,
    backgroundColor: 'white',
    borderRadius: 20,
    width: "90%",
    height: "60%",
    alignItems: 'center',
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 4,
    elevation: 5,
  },
  button: {
    borderRadius: 20,
    padding: 10,
    elevation: 2,
    position: "absolute",
    right: 0,
    bottom: 0,
    margin: 15,
  },
  button2: {
    borderRadius: 20,
    padding: 10,
    elevation: 2,
    position: "absolute",
    left: 0,
    bottom: 0,
    margin: 15,
  },
  buttonOpen: {
    backgroundColor: '#F194FF',
  },
  buttonClose: {
    backgroundColor: 'red',
  },
  buttonClose2: {
    backgroundColor: '#9beb34',
  },
  textStyle: {
    color: 'white',
    fontWeight: 'bold',
    textAlign: 'center',
  },
  modalText: {
    marginBottom: 15,
    textAlign: 'center',
    fontWeight: "bold",
    fontSize: 24,
    margin: 10
  },
  btn: {
    position: "absolute",
    right: 0,
    bottom: 0,
    backgroundColor: "#0782F9",
    padding: 10,
    borderRadius: 30,
    alignItems: "center",
    margin: 15
  },
  input: {
    width: "90%",
    backgroundColor: "white",
    paddingHorizontal: 15,
    paddingVertical: 10,
    borderRadius: 10,
    marginTop: 5,
    borderBottomWidth: 2,
    borderBottomColor: "#313131"
  },
  dateComponent: {
    width: "60%",
    marginTop: 20,
    marginBottom: 5,
  },
  btnDatePicker: {
    padding: 15,
    marginHorizontal: 10,
    alignItems: "center",
    backgroundColor: "#0782F9",
    marginTop: 20,
    width: "40%",
    borderRadius: 15,
  },
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 03:54:11