I am creating a Next.js app that uses a Flask API for the backend. I have a Main component that displays fetched data from the Flask API and displays it. However, I struggle with one issue in the beginning. Whenever I deploy my Flask API after my Next.js app, the Next.js app calls render the object that is supposed to store the fetched data as null, meaning that nothing is returned from the API, causing an error. However, whenever I refresh the app afterwards or start my Flask API before Next.js app, it works fine. I think this is because the Flask API hasn’t fully been deployed or hosted whenever I run it after my Next.js app but I don’t know how to fix this issue.
I tried running it afterwards with some time and just waiting before loading it, using a debouncer (which is still in my code because it helped with reducing API calls), and other things. I still don’t know how to fix it.
import React, { useState } from 'react'
import axios from 'axios'
import Image from 'next/image'
import SectionColumn from './SectionColumn'
import Loading from './Loading'
const MainLayout = ({isLoading, menuData} : {isLoading: boolean, menuData: string | any}) => {
console.log(menuData)
if (isLoading) {
return (
<div className='flex justify-center items-center h-full'>
<div className="loader"></div> {/* This is where your GSAP animation will be applied */}
</div>
);
}
if (!menuData || menuData === 'Unavailable' ) {
return <div className='flex flex-col items-center justify-center h-full text-gray-200'>
<Image src='/texas-cleared-logo.png' width={128} height={128} alt='Longhorns Logo'/>
<h2>Sorry, but this is not open! Try again later!</h2>
</div>
}
return (
<div className='w-3/4 my-12'>
<div className='hidden lg:flex flex-row justify-between items-start gap-28 mx-4'>
{Object.entries(menuData).map(([mealType, sections]: [string, any]) => (
<SectionColumn key={mealType} sectionName={mealType} sections={sections} />
))}
</div>
<div className='lg:hidden flex flex-col justify-around items-center gap-12'>
{Object.entries(menuData).map(([mealType, sections]: [string, any]) => (
<SectionColumn key={mealType} sectionName={mealType} sections={sections} />
))}
</div>
</div>
)
}
export default MainLayout
import axios from 'axios'
const API_BASE_URL = 'http://127.0.0.1:5000'
export const fetchDiningHalls = async () => {
try {
const response = await axios.get(`${API_BASE_URL}/return_location_halls`)
return response.data.dining_halls
} catch (error) {
console.error(`Error fetching data`, error)
return []
}
}
export const fetchDatesForDiningHall = async (diningHall: string) => {
try {
const response = await axios.get(`${API_BASE_URL}/return_dates/${diningHall}`);
return response.data.dates
} catch (error) {
console.error(`Error fetching dates for dining hall ${diningHall}:`, error)
return []
}
}
export const fetchMenuDataForJ2Dining = async () => {
try {
const response = await axios.get(`${API_BASE_URL}/return_meals/J2 Dining/Wednesday, June 31`);
return response.data;
} catch (error) {
console.error(`Error fetching menu data for dining hall ${'J2 Dining'} on date ${'June 31st'}:`, error);
return null;
}
};
export const fetchMenuData = async (diningHall: string, date: string) => {
try {
const response = await axios.get(`${API_BASE_URL}/return_meals/${diningHall}/${date}`, {
params: { hall: diningHall, date: date }
});
return response.data;
} catch (error) {
console.error(`Error fetching menu data for dining hall ${diningHall} on date ${date}:`, error);
return null;
}
};
export const handleUpvote = async (itemName: string, sectionName: string) => {
}
export const handleDownvote = async (itemName: string, sectionName: string) => {
}
from flask import Flask, jsonify
from flask_cors import CORS
import boto3
import os
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
cors = CORS(app)
TABLE_NAME = os.environ['TABLE_NAME']
db = boto3.resource('dynamodb')
table = db.Table(TABLE_NAME)
def get_latest_data():
try:
response = table.scan()
items = response.get('Items', [])
if not items:
print('No items available!')
items_sorted = sorted(items, key=lambda x: x['timestamp'], reverse=True)
latest_data = list(items_sorted[0]['data'].values())[0]
return latest_data
except Exception as e:
print(str(e))
return None
@app.route('/')
def home():
return jsonify({'message': 'Hello World!'})
@app.route('/return_dates/<string:dining_hall>', methods=['GET'])
def return_dates(dining_hall):
data = get_latest_data()
if data is None:
return jsonify({'error': 'No data available'}, 200)
dates = data[dining_hall]['dates']
return jsonify({'dates': dates})
@app.route('/return_location_halls', methods=['GET'])
def return_location_halls():
data = get_latest_data()
if data is None:
return jsonify({'error': 'No data available'}, 200)
dining_halls = list(data.keys())
return jsonify({'dining_halls': dining_halls})
@app.route('/return_meals/<string:dining_hall>/<string:date>', methods=['GET'])
def return_meals_dictionary(dining_hall, date):
data = get_latest_data()
if data is None:
return jsonify({'error': 'No data available'}, 200)
menu_items = data[dining_hall]['menus']
for index, item in enumerate(menu_items):
if list(item.keys())[0] == date:
return jsonify({'menu_items': menu_items[index][date]})
return jsonify({'menu_items': menu_items})
if __name__ == '__main__':
app.run(debug=True)
@app.route('/handle_upvote/<string:dining_hall>/<string:item_name>', methods=['POST'])
def handle_upvote(dining_hall, item_name):
pass
@app.route('/handle_downvote/<string:dining_hall>/<string:item_name>', methods=['POST'])
def handle_downvote(dining_hall, item_name):
pass