簡體   English   中英

需要幫助弄清楚我的數據操作/道具傳遞 React-Native/react-native-calendars

[英]Need help figuring out my data manipulation/prop passing React-Native/react-native-calendars

我正在使用react-native-calendarsaws-amplifymomentuuid來獲取數據,將日期數據顯示為日歷上標記的點,然后允許用戶打開一個模式,其中包含來自我的 React Native 查詢中的日期項(世博會)應用程序。 我收到一個錯誤,這對我來說沒有多大意義,我認為這是我處理數據操作/處理或屬性傳遞的方式:

TypeError: undefined is not an object (evaluating 'item.createdAt')

這可能是一個很長的解釋,但我會盡我所能解釋發生了什么以及我認為錯誤來自哪里。

我有一個返回項目列表的查詢,在這種情況下,它們是已發送給用戶的通知。 我有這個 function,它處理獲取數據和構建數據,以便我可以將項目傳遞給子組件。 以下是我如何查詢信息以及如何存儲數據。

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

上面的結果在我記錄它時將我的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",
    },
  },
}

雖然我的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,
  },
}

到目前為止,一切正常,但在下面的代碼中,當我處理當天的壓力以及隨后打開模態時,這是TypeError: undefined is not an object (evaluating 'item.createdAt')發生:

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;

在上面的代碼中, setDayNotificationItemsshowDayModal從父組件傳遞到CalendarCard ,可以在這里看到:

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;

由此,當用戶按下日期時,上面顯示的數據從CalendarCard傳遞到TrackerScreen 然后,這會觸發CalendarDayModal變得可見並呈現此處顯示的幾個組件:

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;

在這里我們看到結束組件,其中TypeError: undefined is not an object (evaluating 'item.createdAt')正在顯現,其中<DayNotifications/>組件正在嘗試使用上面定義的數據。 但是,我認為部分問題可能與我將數據過濾到 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);
    };

下面是我的DayNotifications組件,發生錯誤的地方:

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;

那么,為什么我的日歷正在呈現點,這些點是從查詢產生的 object 的createdAt字段派生的,但是在上面顯示的轉換之后,我的DayNotifications組件說item.createdAt是未定義的? 我傳遞這些數據的方式是否有錯誤,或者我存儲數據的方式是否有錯誤,或者更可能是我在將數據傳遞給DayNotifications之前過濾數據的方式有問題(這是我的想法是什么,但還不知道問題是什么)?

已解決,我假設我的findValueByPrefix將返回一致的鍵,但在某些嵌套對象中建立鍵值(純粹為了唯一鍵值的目的)實際上並不是以任何順序建立鍵。 因此傳遞Object.entries(dayNotificationItems).forEach(([k,v]) => dayItems.push(v[ ${k} ])); 會嘗試通過 object 中不存在的鍵來引用嵌套的 object(在某些情況下可能只是巧合,這就是為什么這個錯誤令人惱火)。

我選擇忽略鍵並只提取值,因為鍵只是為了確保可能相同的對象在任何步驟都不會被覆蓋或刪除。 這是我必須做的所有事情:

...
    const dayItems = [];
    Object.values(dayNotificationItems).forEach(item => {
        Object.values(item).forEach(v => {
            dayItems.push(v)
        });
    });
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM