Hello fellow developers,
I’m junior developer and I’m working on a project with big nested object (example bellow) which ideally I want to use as react state that can be accessed from multiple places but I don’t know which approach is best for this solution as I don’t have many experiences yet. If you could give me some advice, code example or link to some tutorial or blog, it would be very helpful.
My current approach (example bellow) is to use useContext without useReducer because I just don’t want to just export dispatch because I think is kinda ugly or not programmer friendly as you always have to define different type and payloads. Maybe I could wrap dispatch it in the functions but I’m just not sure about it. I was also thinking about using Redux, but I don’t use that yet and according to what read that it can be overkill for this.
Thank you in advance.
{
id: string,
name: string,
sections: [{
id: string,
pos_x: number,
pos_y: number,
rows: number,
columns: number,
curvature: number,
skew: number,
rotation: number,
section_type: string,
name: string,
seats: [{
id: string,
row: number,
column: number,
is_disabled: boolean,
category: string,
name: string,
created_at: string,
updated_at: string,
is_reserved: boolean,
reserved_at: string,
status: string,
ticket: number
}],
total_seats: number,
created_at: string,
updated_at: string,
available_seats: number,
purchased_seats: number,
reserved_seats: number
}],
creator: number,
account: number,
is_editable: boolean,
total_seats: number,
created_at: string,
updated_at: string,
event: number,
available_seats: number,
purchased_seats: number,
reserved_seats: number
}
import React, {createContext, FC, useState} from 'react';
import {Seat, SeatMap, Section} from "../../types/seatmapData";
type UpdateSelectedSectionProps = (section: Section, seatIndex: number) => Section
export interface ISeatMap {
id: string,
name: string,
sections: Section[],
creator: number,
account: number,
isEditable: boolean,
totalSeats: number,
createdAt: string,
updatedAt: string,
event: number,
availableSeats: number,
purchasedSeats: number,
reservedSeats: number
}
export interface ISeatMapContext extends ISeatMap {
setName: (name: string) => void;
setSections: (section: Section[]) => void;
setId: (id: string) => void;
setCreator: (creator: number) => void;
setAccount: (account: number) => void;
setIsEditable: (isEditable: boolean) => void;
setTotalSeats: (totalSeats: number) => void;
setCreatedAt: (createdAt: string) => void;
setUpdatedAt: (updatedAt: string) => void;
setEvent: (event: number) => void;
setAvailableSeats: (availableSeats: number) => void;
setPurchasedSeats: (purchasedSeats: number) => void;
setReservedSeats: (reservedSears: number) => void;
addSectionToSelected: (section: Section) => void;
removeSectionsFromSelected: (section: Section) => void;
clearSelectedSections: () => void;
addSeatToSelected: (section: Section, seat: Seat) => void;
removeSeatFromSelected: (section: Section, seat: Seat) => void;
clearSelectedSeats: () => void;
addSection: (section: Section) => void;
removeSection: (section: Section) => void;
removeSelectedSections: () => void;
updateSection: (section: Section) => void;
updateSelectedSeats: (updateFunction: UpdateSelectedSectionProps) => boolean;
reserveSelectedSeats: (reserved: boolean, reservedAt: Date) => void;
purchaseSelectedSeat: () => void;
disableSelectedSeats: (disabled: boolean) => void;
getSeatMap: () => void;
}
export const SeatMapContext = createContext<ISeatMapContext>(null!);
export interface SeatMapProviderProps extends FC {
children: any;
initialValue: SeatMap;
}
const SeatMapProvider = ({ children, initialValue }: SeatMapProviderProps) => {
const [name, setName] = useState<string>(initialValue.name)
const [sections, setSections] = useState<Section[]>(initialValue.sections)
const [id, setId] = useState<string>(initialValue.id)
const [creator, setCreator] = useState<number>(initialValue.creator)
const [account, setAccount] = useState<number>(initialValue.account)
const [isEditable, setIsEditable] = useState<boolean>(initialValue.is_editable)
const [totalSeats, setTotalSeats] = useState<number>(initialValue.total_seats)
const [createdAt, setCreatedAt] = useState<string>(initialValue.created_at)
const [updatedAt, setUpdatedAt] = useState<string>(initialValue.updated_at)
const [event, setEvent] = useState<number>(initialValue.event)
const [availableSeats, setAvailableSeats] = useState<number>(initialValue.available_seats)
const [purchasedSeats, setPurchasedSeats] = useState<number>(initialValue.purchased_seats)
const [reservedSeats, setReservedSeats] = useState<number>(initialValue.reserved_seats)
const [selectedSections, setSelectedSections] = useState<Section[]>([]);
const [selectedSeats, setSelectedSeats] = useState<{section: Section, seat: Seat}[]>([]);
const addSectionToSelected = (section: Section) => {
setSelectedSections(prev => [...prev, section])
}
const removeSectionsFromSelected = (section: Section) => {
setSelectedSections(prev => prev.filter(s => s.id === section.id))
}
const clearSelectedSections = () => {
setSelectedSections([])
}
const addSeatToSelected = (section: Section, seat: Seat) => {
setSelectedSeats(prev => [...prev, {section: section, seat: seat}])
}
const removeSeatFromSelected = (section: Section, seat: Seat) => {
setSelectedSeats(prev => prev.filter(s => s.section.id === section.id && s.seat.id == seat.id))
}
const clearSelectedSeats = () => {
setSelectedSeats([])
}
const addSection = (section: Section) => {
setSections(prevState => [...prevState, section])
}
const removeSection = (section: Section) => {
setSections(prevState => prevState.filter(s => s.id == section.id))
}
const removeSelectedSections = () => {
if(selectedSections.length == 0) return
setSections(prevState => {
const notSelected: Section[] = []
prevState.forEach(s => {
let isSelected = false
selectedSections.forEach(selected => {
if(selected.id == s.id) isSelected = true
})
if(!isSelected) notSelected.push(s)
})
return notSelected
})
}
const updateSection = (section: Section) => {
setSections((prevState) => {
const index = prevState.findIndex(s => s.id === section.id)
sections[index] = section
return sections
})
}
const updateSelectedSeats = (updateFunction: UpdateSelectedSectionProps): boolean => {
if(selectedSections.length == 0 || selectedSeats.length == 0) return false
const updateTime = new Date().toISOString()
setSections(sections => {
selectedSeats.forEach(({section, seat}) => {
const sectionIndex = sections.findIndex(s => s.id === section.id)
const seatIndex = sections[sectionIndex].seats.findIndex(s => s.id === seat.id)
const newSection = updateFunction(sections[sectionIndex], seatIndex);
sections[sectionIndex] = newSection
sections[sectionIndex].updated_at = updateTime
})
return sections
})
setUpdatedAt(updateTime)
return true
}
const reserveSelectedSeats = (reserved: boolean, reservedAt: Date) => {
const updated = updateSelectedSeats((section, seatIndex) => {
section.seats[seatIndex].is_reserved = reserved
section.seats[seatIndex].reserved_at = reservedAt.toISOString()
return section
})
if(updated) setReservedSeats(prev => reserved ? ++prev : --prev)
}
const purchaseSelectedSeat = () => {
}
const disableSelectedSeats = (disabled: boolean) => {
const updated = updateSelectedSeats((section, seatIndex) => {
section.seats[seatIndex].is_disabled = disabled
if(disabled) section.total_seats--
else section.total_seats++
return section
})
if(updated) setTotalSeats(prev => disabled ? --prev : ++prev)
}
const getSeatMap = (): SeatMap => {
return {
name: name,
sections: sections,
id: id,
creator: creator,
account: account,
is_editable: isEditable,
total_seats: totalSeats,
created_at: createdAt,
updated_at: updatedAt,
event: event,
available_seats: availableSeats,
purchased_seats: purchasedSeats,
reserved_seats: reservedSeats,
}
}
return (
<SeatMapContext.Provider value={{
name, setName,
sections, setSections,
id, setId,
creator, setCreator,
account, setAccount,
isEditable, setIsEditable,
totalSeats, setTotalSeats,
createdAt, setCreatedAt,
updatedAt, setUpdatedAt,
event, setEvent,
availableSeats, setAvailableSeats,
purchasedSeats, setPurchasedSeats,
reservedSeats, setReservedSeats,
addSectionToSelected,
addSeatToSelected,
clearSelectedSeats,
clearSelectedSections,
purchaseSelectedSeat,
removeSeatFromSelected,
removeSectionsFromSelected,
getSeatMap,
addSection,
removeSection,
updateSection,
removeSelectedSections,
updateSelectedSeats,
reserveSelectedSeats,
disableSelectedSeats
}}>
{children}
</SeatMapContext.Provider>
)
};
export default SeatMapProvider;