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
相关产品推荐
相关产品推荐

