When I call on getFormattedDate:
export function getFormattedDate(date) {
// return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate() +1}`
return date.toISOString().slice(0, 10)
}
In this line:
<Text style={styles.textBase}>{getFormattedDate(date)}</Text>
I get "TypeError: date.toISOString is not a function (it is undefined)"
The data is now coming from mongodb instead of a dummy_expenses array and I can't figure out why getFormatted date does not recognize it as a date. From my research, this error happens because the piece of data being passed to it is not of type 'date'. I console logged the data before and after I changed where the data is coming from and both are date types. If you need any more information about this please let me know.
Before changes:
LOG Expense Item Shoes 2023-07-29T00:00:00.000Z
After changes:
LOG Expense Item EHDN 2023-08-09T00:00:00.000Z
The data is coming from expense-context.js. Here is the file before expense-context was connected to mongodb:
import { createContext, useReducer } from 'react'
const DUMMY_EXPENSES = [
{
id: 'e1',
description: 'Shoes',
amount: 59.99,
date: new Date('2023-7-29'),
}
]
export const ExpensesContext = createContext({
expenses: [],
addExpense: ({description, amount, date}) => { },
deleteExpense: (id) => { },
updateExpense: (id, { description, amount, date }) => { },
})
function expensesReducer(state, action) {
switch (action.type) {
case 'ADD':
const id = new Date().toString() + Math.random().toString()
return [{...action.payload, id: id},...state]
case 'UPDATE':
const updatableExpenseIndex = state.findIndex((expense) => expense.id === action.payload.id)
const updatableExpense = state[updatableExpenseIndex]
const updatedItem = { ...updatableExpense, ...action.payload.data }
const updatedExpenses = [...state]
updatedExpenses[updatableExpenseIndex] = updatedItem
return updatedExpenses
case 'DELETE':
return state.filter((expense) => expense.id !== action.payload )
default:
return state
}
}
function ExpensesContextProvider({ children }) {
const [expensesState, dispatch] = useReducer(expensesReducer, DUMMY_EXPENSES)
function addExpense(expenseData) {
dispatch({ type: 'ADD', payload: expenseData })
}
function deleteExpense(id) {
dispatch({ type: 'DELETE', payload: id })
}
function updateExpense(id, expenseData) {
dispatch({ type: 'UPDATE', payload: { id: id, data: expenseData } })
}
const value = {
expenses: expensesState,
addExpense: addExpense,
deleteExpense: deleteExpense,
updateExpense: updateExpense
}
return (
<ExpensesContext.Provider value={value}>{children}</ExpensesContext.Provider>
)
}
export default ExpensesContextProvider
Here is expense-context.js after I connected it to mongodb:
import { createContext, useReducer } from 'react';
import useFetchExpenses from '../hooks/useFetchExpenses'; // Import the custom hook
import axios from 'axios';
// ...
export const ExpensesContext = createContext({
expenses: [],
addExpense: ({ description, amount, date }) => { },
setExpenses: (expenses) => {},
deleteExpense: (id) => { },
updateExpense: (id, { description, amount, date }) => {},
})
function expensesReducer(state, action) {
switch (action.type) {
case 'ADD':
const id = new Date().toString() + Math.random().toString();
return [{ ...action.payload, id: id }, ...state];
case 'UPDATE':
const updatableExpenseIndex = state.findIndex(
(expense) => expense.id === action.payload.id
);
const updatableExpense = state[updatableExpenseIndex];
const updatedItem = { ...updatableExpense, ...action.payload.data };
const updatedExpenses = [...state];
updatedExpenses[updatableExpenseIndex] = updatedItem;
return updatedExpenses;
case 'DELETE':
return state.filter((expense) => expense.id !== action.payload);
case 'SET_EXPENSES':
// setExpenses()
return action.payload
default:
return state;
}
}
function ExpensesContextProvider({ children }) {
const [expensesState, dispatch] = useReducer(expensesReducer, []);
// Fetch expenses using the custom hook
const { expenses, loading, error } = useFetchExpenses();
console.log("useReducer data", expenses)
// Rest of your CRUD functions (addExpense, deleteExpense, updateExpense)
// Create: Add a function to create a new expense document in the database.
async function addExpense(expenseData) {
try {
const response = await axios.post('http://localhost:8082/expense', expenseData);
dispatch({ type: 'ADD', payload: response.data });
} catch (error) {
console.error('Error adding expense:', error);
}
}
async function setExpenses() {
try {
const response = await axios.get('http://localhost:8082/expenses');
// const expensesWithValidDates = response.data.map((expense) => ({
// ...expense,
// date: new Date(expense.date), // Convert date string to Date object
// }));
dispatch({ type: 'SET_EXPENSES', payload: response.data });
} catch (error) {
console.error('Error fetching expenses:', error);
}
}
async function updateExpense(id, expenseData) {
try {
const response = await axios.put(`http://localhost:8082/expenses/${id}`, expenseData);
dispatch({ type: 'UPDATE', payload: { id: id, data: response.data } });
} catch (error) {
console.error('Error updating expense:', error);
}
}
async function deleteExpense(id) {
try {
await axios.delete(`http://localhost:8082/expenses/${id}`);
dispatch({ type: 'DELETE', payload: id });
} catch (error) {
console.error('Error deleting expense:', error);
}
}
const value = {
expenses: expensesState, // Change to use expenses from the hook if needed
addExpense: addExpense,
deleteExpense: deleteExpense,
updateExpense: updateExpense,
setExpenses: expensesState, // Include the fetch function in the context if needed
};
return (
<ExpensesContext.Provider value={value}>
{children}
</ExpensesContext.Provider>
);
}
export default ExpensesContextProvider;