Merge pull request #163 from jedmund/catch-api-errors

Basic error handling for API errors in SSR
This commit is contained in:
Justin Edmund 2023-01-23 14:43:48 -08:00 committed by GitHub
commit fd4ba48563
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 213 additions and 175 deletions

View file

@ -15,6 +15,7 @@ import organizeRaids from '~utils/organizeRaids'
import useDidMountEffect from '~utils/useDidMountEffect'
import { elements, allElement } from '~data/elements'
import { emptyPaginationObject } from '~utils/emptyStates'
import { printError } from '~utils/reportError'
import GridRep from '~components/GridRep'
import GridRepCollection from '~components/GridRepCollection'
@ -350,50 +351,54 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex
// Set headers for server-side requests
setUserToken(req, res)
// Fetch and organize raids
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
try {
// Fetch and organize raids
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
// Create filter object
const filters: FilterObject = extractFilters(query, raids)
const params = {
params: { ...filters },
}
// Create filter object
const filters: FilterObject = extractFilters(query, raids)
const params = {
params: { ...filters },
}
// Set up empty variables
let user: User | null = null
let teams: Party[] | null = null
let meta: PaginationObject = emptyPaginationObject
// Set up empty variables
let user: User | null = null
let teams: Party[] | null = null
let meta: PaginationObject = emptyPaginationObject
// Perform a request only if we received a username
if (query.username) {
const response = await api.endpoints.users.getOne({
id: query.username,
params,
})
// Perform a request only if we received a username
if (query.username) {
const response = await api.endpoints.users.getOne({
id: query.username,
params,
})
// Assign values to pass to props
user = response.data.profile
// Assign values to pass to props
user = response.data.profile
if (response.data.profile.parties) teams = response.data.profile.parties
else teams = []
if (response.data.profile.parties) teams = response.data.profile.parties
else teams = []
meta.count = response.data.meta.count
meta.totalPages = response.data.meta.total_pages
meta.perPage = response.data.meta.per_page
}
meta.count = response.data.meta.count
meta.totalPages = response.data.meta.total_pages
meta.perPage = response.data.meta.per_page
}
return {
props: {
user: user,
teams: teams,
meta: meta,
raids: raids,
sortedRaids: sortedRaids,
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
return {
props: {
user: user,
teams: teams,
meta: meta,
raids: raids,
sortedRaids: sortedRaids,
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
}
} catch (error) {
printError(error, 'axios')
}
}

View file

@ -5,11 +5,12 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import Party from '~components/Party'
import { appState } from '~utils/appState'
import { groupWeaponKeys } from '~utils/groupWeaponKeys'
import api from '~utils/api'
import organizeRaids from '~utils/organizeRaids'
import setUserToken from '~utils/setUserToken'
import api from '~utils/api'
import { appState } from '~utils/appState'
import { groupWeaponKeys } from '~utils/groupWeaponKeys'
import { printError } from '~utils/reportError'
import type { NextApiRequest, NextApiResponse } from 'next'
import type { GroupedWeaponKeys } from '~utils/groupWeaponKeys'
@ -82,32 +83,34 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex
// Set headers for server-side requests
setUserToken(req, res)
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
try {
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
let jobs = await api.endpoints.jobs
.getAll()
.then((response) => {
let jobs = await api.endpoints.jobs.getAll().then((response) => {
return response.data
})
let jobSkills = await api.allJobSkills().then((response) => response.data)
let jobSkills = await api.allJobSkills().then((response) => response.data)
let weaponKeys = await api.endpoints.weapon_keys
.getAll()
.then((response) => groupWeaponKeys(response.data))
let weaponKeys = await api.endpoints.weapon_keys
.getAll()
.then((response) => groupWeaponKeys(response.data))
return {
props: {
jobs: jobs,
jobSkills: jobSkills,
raids: raids,
sortedRaids: sortedRaids,
weaponKeys: weaponKeys,
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
return {
props: {
jobs: jobs,
jobSkills: jobSkills,
raids: raids,
sortedRaids: sortedRaids,
weaponKeys: weaponKeys,
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
}
} catch (error) {
printError(error, 'axios')
}
}

View file

@ -6,17 +6,17 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import Party from '~components/Party'
import { appState } from '~utils/appState'
import { groupWeaponKeys } from '~utils/groupWeaponKeys'
import api from '~utils/api'
import generateTitle from '~utils/generateTitle'
import organizeRaids from '~utils/organizeRaids'
import setUserToken from '~utils/setUserToken'
import api from '~utils/api'
import { appState } from '~utils/appState'
import { groupWeaponKeys } from '~utils/groupWeaponKeys'
import { GridType } from '~utils/enums'
import { printError } from '~utils/reportError'
import type { NextApiRequest, NextApiResponse } from 'next'
import type { GroupedWeaponKeys } from '~utils/groupWeaponKeys'
import { useQueryState } from 'next-usequerystate'
interface Props {
party: Party
@ -154,74 +154,74 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex
// Set headers for server-side requests
setUserToken(req, res)
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
try {
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
let jobs = await api.endpoints.jobs
.getAll()
.then((response) => {
let jobs = await api.endpoints.jobs.getAll().then((response) => {
return response.data
})
let jobSkills = await api
.allJobSkills()
.then((response) => response.data)
let jobSkills = await api.allJobSkills().then((response) => response.data)
let weaponKeys = await api.endpoints.weapon_keys
.getAll()
.then((response) => groupWeaponKeys(response.data))
let weaponKeys = await api.endpoints.weapon_keys
.getAll()
.then((response) => groupWeaponKeys(response.data))
let party: Party | null = null
if (query.party) {
let response = await api.endpoints.parties.getOne({
id: query.party
})
party = response.data.party
} else {
console.log('No party code')
}
function getElement() {
if (party) {
const mainhand = party.weapons.find((weapon) => weapon.mainhand)
if (mainhand && mainhand.object.element === 0) {
return mainhand.element
} else {
return mainhand?.object.element
}
let party: Party | null = null
if (query.party) {
let response = await api.endpoints.parties.getOne({
id: query.party,
})
party = response.data.party
} else {
return 0
console.log('No party code')
}
}
function elementEmoji() {
const element = getElement()
function getElement() {
if (party) {
const mainhand = party.weapons.find((weapon) => weapon.mainhand)
if (mainhand && mainhand.object.element === 0) {
return mainhand.element
} else {
return mainhand?.object.element
}
} else {
return 0
}
}
if (element === 0) return '⚪'
else if (element === 1) return '🟢'
else if (element === 2) return '🔴'
else if (element === 3) return '🔵'
else if (element === 4) return '🟤'
else if (element === 5) return '🟣'
else if (element === 6) return '🟡'
else return '⚪'
}
function elementEmoji() {
const element = getElement()
return {
props: {
party: party,
jobs: jobs,
jobSkills: jobSkills,
raids: raids,
sortedRaids: sortedRaids,
weaponKeys: weaponKeys,
meta: {
element: elementEmoji(),
if (element === 0) return '⚪'
else if (element === 1) return '🟢'
else if (element === 2) return '🔴'
else if (element === 3) return '🔵'
else if (element === 4) return '🟤'
else if (element === 5) return '🟣'
else if (element === 6) return '🟡'
else return '⚪'
}
return {
props: {
party: party,
jobs: jobs,
jobSkills: jobSkills,
raids: raids,
sortedRaids: sortedRaids,
weaponKeys: weaponKeys,
meta: {
element: elementEmoji(),
},
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
}
} catch (error) {
printError(error, 'axios')
}
}

View file

@ -16,6 +16,7 @@ import organizeRaids from '~utils/organizeRaids'
import useDidMountEffect from '~utils/useDidMountEffect'
import { elements, allElement } from '~data/elements'
import { emptyPaginationObject } from '~utils/emptyStates'
import { printError } from '~utils/reportError'
import GridRep from '~components/GridRep'
import GridRepCollection from '~components/GridRepCollection'
@ -352,39 +353,43 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex
// Set headers for server-side requests
setUserToken(req, res)
// Fetch and organize raids
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
try {
// Fetch and organize raids
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
// Create filter object
const filters: FilterObject = extractFilters(query, raids)
const params = {
params: { ...filters },
}
// Create filter object
const filters: FilterObject = extractFilters(query, raids)
const params = {
params: { ...filters },
}
// Set up empty variables
let teams: Party[] | null = null
let meta: PaginationObject = emptyPaginationObject
// Set up empty variables
let teams: Party[] | null = null
let meta: PaginationObject = emptyPaginationObject
// Fetch initial set of saved parties
const response = await api.savedTeams(params)
// Fetch initial set of saved parties
const response = await api.savedTeams(params)
// Assign values to pass to props
teams = response.data.results
meta.count = response.data.meta.count
meta.totalPages = response.data.meta.total_pages
meta.perPage = response.data.meta.per_page
// Assign values to pass to props
teams = response.data.results
meta.count = response.data.meta.count
meta.totalPages = response.data.meta.total_pages
meta.perPage = response.data.meta.per_page
return {
props: {
teams: teams,
meta: meta,
raids: raids,
sortedRaids: sortedRaids,
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
return {
props: {
teams: teams,
meta: meta,
raids: raids,
sortedRaids: sortedRaids,
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
}
} catch (error) {
printError(error, 'axios')
}
}

View file

@ -16,6 +16,7 @@ import organizeRaids from '~utils/organizeRaids'
import useDidMountEffect from '~utils/useDidMountEffect'
import { elements, allElement } from '~data/elements'
import { emptyPaginationObject } from '~utils/emptyStates'
import { printError } from '~utils/reportError'
import GridRep from '~components/GridRep'
import GridRepCollection from '~components/GridRepCollection'
@ -364,38 +365,42 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex
setUserToken(req, res)
// Fetch and organize raids
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
try {
let { raids, sortedRaids } = await api.endpoints.raids
.getAll()
.then((response) => organizeRaids(response.data))
// Create filter object
const filters: FilterObject = extractFilters(query, raids)
const params = {
params: { ...filters },
}
// Create filter object
const filters: FilterObject = extractFilters(query, raids)
const params = {
params: { ...filters },
}
// Set up empty variables
let teams: Party[] | null = null
let meta: PaginationObject = emptyPaginationObject
// Set up empty variables
let teams: Party[] | null = null
let meta: PaginationObject = emptyPaginationObject
// Fetch initial set of parties
const response = await api.endpoints.parties.getAll(params)
// Fetch initial set of parties
const response = await api.endpoints.parties.getAll(params)
// Assign values to pass to props
teams = response.data.results
meta.count = response.data.meta.count
meta.totalPages = response.data.meta.total_pages
meta.perPage = response.data.meta.per_page
// Assign values to pass to props
teams = response.data.results
meta.count = response.data.meta.count
meta.totalPages = response.data.meta.total_pages
meta.perPage = response.data.meta.per_page
return {
props: {
teams: teams,
meta: meta,
raids: raids,
sortedRaids: sortedRaids,
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
return {
props: {
teams: teams,
meta: meta,
raids: raids,
sortedRaids: sortedRaids,
...(await serverSideTranslations(locale, ['common', 'roadmap'])),
// Will be passed to the page component as props
},
}
} catch (error) {
printError(error, 'axios')
}
}

20
utils/reportError.tsx Normal file
View file

@ -0,0 +1,20 @@
import { AxiosError } from 'axios'
function handleError(error: any) {
if (error instanceof Error) return error.message
}
function handleAxiosError(error: any) {
const axiosError = error as AxiosError
return axiosError.response
}
export function printError(error: any, type?: string) {
if (type === 'axios') {
const response = handleAxiosError(error)
console.log(`${response?.status} ${response?.statusText}`)
console.log(response?.data.toJSON())
} else {
console.log(handleError(error))
}
}