[英]Need help figuring out my data manipulation/prop passing React-Native/react-native-calendars
I am using react-native-calendars
, aws-amplify
, moment
and uuid
to fetch data, display date data as dots marked on the calendar and then allow the user to open a modal with that dates items from the query in my React Native (Expo) app.我正在使用
react-native-calendars
、 aws-amplify
、 moment
和uuid
来获取数据,将日期数据显示为日历上标记的点,然后允许用户打开一个模式,其中包含来自我的 React Native 查询中的日期项(世博会)应用程序。 I am getting an error, which isn't making much sense to me, I think it's the way I'm handling data manipulation/processing or property passing:我收到一个错误,这对我来说没有多大意义,我认为这是我处理数据操作/处理或属性传递的方式:
TypeError: undefined is not an object (evaluating 'item.createdAt')
This may be a long explanation, but I will explain to the best of my ability what's happening and where I think the error is coming from.这可能是一个很长的解释,但我会尽我所能解释发生了什么以及我认为错误来自哪里。
I have a query that returns a list of items, in this case they are notifications that have been sent to the user.我有一个返回项目列表的查询,在这种情况下,它们是已发送给用户的通知。 I have this function which handles getting the data and structuring it so that I can pass the items to a sub-component.
我有这个 function,它处理获取数据和构建数据,以便我可以将项目传递给子组件。 Here is how I am querying the info and how I'm storing the data.
以下是我如何查询信息以及如何存储数据。
CalendarCard.js (first half) CalendarCard.js (上半场)
import React, { useEffect, useState } from "react";
import moment from 'moment';
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
import { API } from "aws-amplify";
import { listUserNotifications } from '../../graphql/queries';
...
const CalendarCard = (
{
showCalendarInfoModal,
showDayModal,
setDayNotificationItems,
}) => {
const [markedDates,setMarkedDates] = useState();
const [notificationItems, setNotificationItems] = useState();
const currentMonth = moment().startOf('month').toISOString();
const now = new Date().toISOString();
useEffect(() => {
const recordInitNotifications = (notifications) => {
notifications.forEach((item,i) => {
let id = uuidv4().toString();
let createdAt = item.createdAt;
let notificationDate = moment(createdAt).format('YYYY-MM-DD');
let notificationId = notificationDate+id;
setMarkedDates(prev => ({
...prev,
[notificationDate]: {marked: true, dotColor: 'grey'}
}));
setNotificationItems(prev => ({
...prev,
[notificationId]: {[i]: item}
}));
});
};
const currentNotifications = async () => {
const initNotificationData = await API.graphql({
query: listUserNotifications,
variables: {
filter: {
createdAt: {
between: [currentMonth,now]
}
}
},
authMode: 'AMAZON_COGNITO_USER_POOLS'
});
const initNotifications = initNotificationData.data.listUserNotifications.items;
recordInitNotifications(initNotifications);
};
currentNotifications().catch(console.error);
}, []);
...
// continued below
The result of the above sets my notificationItems
variable as follows when I log it:上面的结果在我记录它时将我的
notificationItems
变量设置如下:
Object {
"2022-04-096d64e695-c377-4790-88bc-4de803f63028": Object {
"0": Object {
"PushToken": "ExponentPushToken[*********************]",
"StackName": "Everydaytest",
"StackSchedule": "{\"Everyday\":{\"dw\":[6,7,1,2,3,4,5],\"type\":\"DAY_WEEK\",\"startDate\":\"2022-04-09T15:00:00.000Z\"}}",
"StackScheduleName": "Everyday",
"UserID": "user",
"createdAt": "2022-04-09T15:00:22.504Z",
"id": "ee520f0a-cd93-47f9-954d-0c5f741daaa7",
"lastReceipt": "{\"stack\":\"patrick2022-04-09T14:52:37.519Z<139029b5-4402-4c08-b41f-b7653e64cb93>ba7cb97d-d6db-4086-82dd-b6a8c79712e5\",\"ticket\":{\"id\":\"e1ba6799-0a03-4126-a1fc-6fc4f39308d2\",\"status\":\"ok\"}}",
"lastReceiptCreated": "2022-04-09T15:00:22.504Z",
"owner": "user",
"updatedAt": "2022-04-09T15:00:22.504Z",
},
},
"2022-04-10213a8a85-7a0a-4e97-80c4-36711381f01f": Object {
"4": Object {
"PushToken": "ExponentPushToken[*********************]",
"StackName": "Pasta",
"StackSchedule": "{\"2 on, 1 off weekdays\":{\"dw\":[0,1,2,3],\"type\":\"DAY_WEEK\",\"startDate\":\"2022-03-13T11:00:00.000Z\"}}",
"StackScheduleName": "2 on, 1 off weekdays",
"UserID": "user",
"createdAt": "2022-04-10T11:00:23.093Z",
"id": "3fb75293-1afd-4a75-bdfd-b27961cd127e",
"lastReceipt": "{\"stack\":\"user2022-03-15T15:10:32.642Z<139029b5-4402-4c08-b41f-b7653e64cb93>d2cb5bf8-49ce-4d07-bbdc-aaa9418aae41\",\"ticket\":{\"id\":\"cb888fe2-a925-4571-9bc4-878ee585323b\",\"status\":\"ok\"}}",
"lastReceiptCreated": "2022-04-10T11:00:23.093Z",
"owner": "user",
"updatedAt": "2022-04-10T11:00:23.093Z",
},
},
"2022-04-1122b29a72-c30f-4a33-a164-0497b33122c0": Object {
"2": Object {
"PushToken": "ExponentPushToken[*********************]",
"StackName": "Pasta",
"StackSchedule": "{\"2 on, 1 off weekdays\":{\"dw\":[0,1,2,3],\"type\":\"DAY_WEEK\",\"startDate\":\"2022-03-13T11:00:00.000Z\"}}",
"StackScheduleName": "2 on, 1 off weekdays",
"UserID": "user",
"createdAt": "2022-04-11T11:00:22.341Z",
"id": "ff0d4f69-2d6b-4db8-90f6-db68c642042c",
"lastReceipt": "{\"stack\":\"user2022-03-15T15:10:32.642Z<139029b5-4402-4c08-b41f-b7653e64cb93>d2cb5bf8-49ce-4d07-bbdc-aaa9418aae41\",\"ticket\":{\"id\":\"dc451865-8b66-4088-93a5-8985d869eb1c\",\"status\":\"ok\"}}",
"lastReceiptCreated": "2022-04-11T11:00:22.341Z",
"owner": "user",
"updatedAt": "2022-04-11T11:00:22.341Z",
},
},
"2022-04-11cc0bdf71-c796-4252-b4aa-9f8ffd7e49a9": Object {
"3": Object {
"PushToken": "ExponentPushToken[*********************]",
"StackName": "Every other skip 4pm",
"StackSchedule": "{\"Every other day\":{\"skip_days\":2,\"type\":\"SKIP_DAYS\",\"startDate\":\"2022-04-11T19:46:34.080Z\"}}",
"StackScheduleName": "Every other day",
"UserID": "user",
"createdAt": "2022-04-11T20:00:22.549Z",
"id": "83cf53f2-9981-4eb1-bc8a-28e833de7e67",
"lastReceipt": "{\"stack\":\"user2022-04-11T19:47:42.994Z<139029b5-4402-4c08-b41f-b7653e64cb93>907e97a3-a438-49e7-bf5f-71ef8b23e7c4\",\"ticket\":{\"id\":\"0a4aa2dd-acb9-4cd2-89f4-5dec0b82337c\",\"status\":\"ok\"}}",
"lastReceiptCreated": "2022-04-11T20:00:22.549Z",
"owner": "user",
"updatedAt": "2022-04-11T20:00:22.549Z",
},
},
"2022-04-11dbf1fc4b-ca38-4ac5-b660-7b10195fc891": Object {
"1": Object {
"PushToken": "ExponentPushToken[*********************]",
"StackName": "Everydaytest",
"StackSchedule": "{\"Everyday\":{\"dw\":[6,7,1,2,3,4,5],\"type\":\"DAY_WEEK\",\"startDate\":\"2022-04-09T15:00:00.000Z\"}}",
"StackScheduleName": "Everyday",
"UserID": "user",
"createdAt": "2022-04-11T15:00:22.660Z",
"id": "597233b0-7327-4b13-923c-b3b9073c6747",
"lastReceipt": "{\"stack\":\"user2022-04-09T14:52:37.519Z<139029b5-4402-4c08-b41f-b7653e64cb93>ba7cb97d-d6db-4086-82dd-b6a8c79712e5\",\"ticket\":{\"id\":\"38eef4db-4914-4885-ae5e-7de509b7d424\",\"status\":\"ok\"}}",
"lastReceiptCreated": "2022-04-11T15:00:22.660Z",
"owner": "user",
"updatedAt": "2022-04-11T15:00:22.660Z",
},
},
}
While my markedDates
state looks like this:虽然我的
markedDates
state 看起来像这样:
Object {
"2022-04-09": Object {
"dotColor": "grey",
"marked": true,
},
"2022-04-10": Object {
"dotColor": "grey",
"marked": true,
},
"2022-04-11": Object {
"dotColor": "grey",
"marked": true,
},
}
Up to this point, everything works, but in the following code when I am handling the pressing of the day, and the subsequent opening of the modal, this is where the TypeError: undefined is not an object (evaluating 'item.createdAt')
occurs:到目前为止,一切正常,但在下面的代码中,当我处理当天的压力以及随后打开模态时,这是
TypeError: undefined is not an object (evaluating 'item.createdAt')
发生:
CalendarCard.js (second half) CalendarCard.js (下半场)
// continuation of above code
...
function findValueByPrefix(obj,string) {
let items = [];
for (let property in obj) {
if (obj.hasOwnProperty(property) &&
property.toString().startsWith(string)) {
items.push(obj[property]);
};
};
return items;
};
const handleDayPress = (day) => {
const openModalWithData = (dayNotifications) => {
setDayNotificationItems(dayNotifications);
showDayModal();
};
const dayString = day.dateString;
let dayNotifications = findValueByPrefix(notificationItems,dayString);
openModalWithData(dayNotifications);
};
return (
<Card>
<Card.Title title='My History'/>
<Calendar
onMonthChange={month => handleMonthChange(month)}
markedDates={markedDates}
onDayPress={day => handleDayPress(day)}
/>
<Card.Content/>
</Card>
);
};
export default CalendarCard;
In the above code, setDayNotificationItems
and showDayModal
are passed into CalendarCard
from the parent component which can be seen here:在上面的代码中,
setDayNotificationItems
和showDayModal
从父组件传递到CalendarCard
,可以在这里看到:
TrackerScreen.js TrackerScreen.js
import React, { useState } from "react";
import { ScrollView, View } from "react-native";
import { Portal } from "react-native-paper";
import { SafeAreaView } from "react-native-safe-area-context";
import CalendarDayModal from "../components/modals/CalendarDayModal";
import CalendarCard from "../components/tracker/CalendarCard";
const TrackerScreen = () => {
const [dayNotificationItems, setDayNotificationItems] = useState();
const [dayModalVisible, setDayModalVisible] = useState(false);
const showDayModal = () => setDayModalVisible(true);
const hideDayModal = () => setDayModalVisible(false);
return (
<SafeAreaView>
<Portal>
<CalendarDayModal
dayModalVisible={dayModalVisible}
hideDayModal={hideDayModal}
dayNotificationItems={dayNotificationItems}
/>
</Portal>
<ScrollView>
<View>
<CalendarCard
showDayModal={showDayModal}
setDayNotificationItems={setDayNotificationItems}
/>
</View>
</ScrollView>
</SafeAreaView>
);
};
export default TrackerScreen;
From this, the data shown above is passed up from CalendarCard
to TrackerScreen
when a user presses the day.由此,当用户按下日期时,上面显示的数据从
CalendarCard
传递到TrackerScreen
。 This then triggers the CalendarDayModal
to become visible and render a few components shown here:然后,这会触发
CalendarDayModal
变得可见并呈现此处显示的几个组件:
CalendarDayModal.js CalendarDayModal.js
import React from "react";
import { View } from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import { Caption, Headline, IconButton, Modal } from "react-native-paper";
import DayNotifications from "../tracker/DayNotifications";
const CalendarDayModal = (
{
dayModalVisible,
hideDayModal,
dayNotificationItems
}) => {
const RenderDayNotifications = () => {
if (dayNotificationItems.length > 0) {
return (
<View style={{flexDirection:'column',paddingVertical:5}}>
<Headline>Tracked Stacks</Headline>
<Caption>The things you tracked this day</Caption>
<DayNotifications
dayNotificationItems={dayNotificationItems}
/>
</View>
);
} else return(<View></View>);
};
return (
<Modal
visible={dayModalVisible}
onDismiss={hideDayModal}
contentContainerStyle={{
backgroundColor:'#D7FFFF',
width:'100%',
height: '100%',
alignSelf:'center'
}}
>
<IconButton
icon='check'
size={20}
style={{paddingTop: 10,position:'absolute',right:0,top:0}}
onPress={hideDayModal}
/>
<ScrollView style={{width: '95%',alignSelf:'center'}}>
<RenderDayNotifications/>
</ScrollView>
</Modal>
);
};
export default CalendarDayModal;
Here we see the end component where the TypeError: undefined is not an object (evaluating 'item.createdAt')
is manifesting itself, where the <DayNotifications/>
component is attempting to consume the data defined above.在这里我们看到结束组件,其中
TypeError: undefined is not an object (evaluating 'item.createdAt')
正在显现,其中<DayNotifications/>
组件正在尝试使用上面定义的数据。 However, I believe part of the issue may be with my approach to filtering my data to select the items which match the day
object from onDayPress={day => handleDayPress(day)}
in the CalendarCard
component where I use this function:但是,我认为部分问题可能与我将数据过滤到 select 的方法有关,这些项目与我使用此 function 的
CalendarCard
组件中的onDayPress={day => handleDayPress(day)}
匹配day
object:
function findValueByPrefix(obj,string) {
let items = [];
for (let property in obj) {
if (obj.hasOwnProperty(property) &&
property.toString().startsWith(string)) {
items.push(obj[property]);
};
};
return items;
};
const handleDayPress = (day) => {
const openModalWithData = (dayNotifications) => { setDayNotificationItems(dayNotifications);
showDayModal();
};
const dayString = day.dateString;
let dayNotifications = findValueByPrefix(notificationItems,dayString);
openModalWithData(dayNotifications);
};
Below is my DayNotifications
component, where the error is happening:下面是我的
DayNotifications
组件,发生错误的地方:
DayNotifications.js DayNotifications.js
import React, { useState } from "react";
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
import moment from 'moment';
import { View } from "react-native";
import { Caption, Card, Subheading, Text } from "react-native-paper";
const DayNotifications = ({dayNotificationItems}) => {
const dayItems = [];
Object.entries(dayNotificationItems).forEach(([k,v]) => dayItems.push(v[`${k}`]));
const NotificationItemCard = ({item}) => {
let deliveryDate = moment(item.createdAt).format('dddd, MMMM Do YYYY');
// ^ ERROR TRIGGERED HERE
let deliveryTime = moment(item.createdAt).format('h:mma');
return(
<Card>
<Card.Title title={deliveryDate} subtitle={deliveryTime}/>
<View style={{
flexDirection: 'column',
width: '90%',
alignSelf:'center',
paddingBottom: 5
}}
>
<View style={{
flexDirection: 'col',
paddingVertical: 10
}}
>
<Subheading>{item.StackName}</Subheading>
<Caption>{item.StackScheduleName}</Caption>
</View>
</View>
</Card>
);
};
return (
<View style={{
width: '95%',
alignContent: 'center',
alignSelf:'center'
}}
>
{dayItems.map((item) =>
<NotificationItemCard key={uuidv4()} item={item}/>
)
}
</View>
);
};
export default DayNotifications;
So, why is it that my calendar is rendering the dots, which the dat is derived from the createdAt
field from the object resulting from the query, but after the transformations shown above, my DayNotifications
component says that item.createdAt
is undefined?那么,为什么我的日历正在呈现点,这些点是从查询产生的 object 的
createdAt
字段派生的,但是在上面显示的转换之后,我的DayNotifications
组件说item.createdAt
是未定义的? Is there an error with the way I'm passing down this data or is the error with the way I am storing the data or more likely is it an issue with the way I'm filtering the data before passing it to DayNotifications
(which is what I think but have no idea what the issue is, yet)?我传递这些数据的方式是否有错误,或者我存储数据的方式是否有错误,或者更可能是我在将数据传递给
DayNotifications
之前过滤数据的方式有问题(这是我的想法是什么,但还不知道问题是什么)?
Solved, I was assuming that my findValueByPrefix
was going to return consistent keys, but the establishment of the key value in some nested objects (purely for unique key values purposes) was not in fact establishing keys in any order.已解决,我假设我的
findValueByPrefix
将返回一致的键,但在某些嵌套对象中建立键值(纯粹为了唯一键值的目的)实际上并不是以任何顺序建立键。 Hence passing Object.entries(dayNotificationItems).forEach(([k,v]) => dayItems.push(v[
${k} ]));
因此传递
Object.entries(dayNotificationItems).forEach(([k,v]) => dayItems.push(v[
${k} ]));
would try to reference the nested object by a key that was not present in the object (it may have been in some instances just by coincidence, which is why this error was infuriating).会尝试通过 object 中不存在的键来引用嵌套的 object(在某些情况下可能只是巧合,这就是为什么这个错误令人恼火)。
I elected to ignore the keys and just extract the values, since the keys were only there to ensure that objects which may be identical would not be overwritten or de-duped at any step.我选择忽略键并只提取值,因为键只是为了确保可能相同的对象在任何步骤都不会被覆盖或删除。 Here's all I had to do:
这是我必须做的所有事情:
...
const dayItems = [];
Object.values(dayNotificationItems).forEach(item => {
Object.values(item).forEach(v => {
dayItems.push(v)
});
});
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.