Info
- zustand ์ฌ์ฉ
- ์ฌ์ฉ ์ด์ : ํ ์ํ๊ด๋ฆฌ๋ณด๋ค ๋ฌ๋ ์ปค๋ธ๊ฐ ๋ฎ๊ณ ๊ด๋ฆฌ ํฌ์ธํธ๊ฐ ์ ์.
- store์ ๊ตฌ์กฐ๋ ๋จ์ํ๊ฒ ๋ฐ์ดํฐ์ CRUD๋ง ๋ด๋น
- ๋ณต์กํ ๋ก์ง๋ค์ ๋ชจ๋ service layer์์ ์ฒ๋ฆฌํจ.
- ์ญํ ์์ผ๋ก๋ ํ๋ฉด์์ ๊ตฌ๋ ์ค์ธ repository๋ผ๊ณ ๋ณผ ์ ์์.
Creation
- ์๋จ์ interface ์ ์ ํ์.
- use{name}Store.ts ๋ค์ด๋ฐ ๊ท์น ์ฌ์ฉ.
- ๋ด๋ถ fields ๋ค์ด๋ฐ ๊ท์น์ ๋ฐ๋ก ์์ด ์ ์ฅํ ๊ฐ์ ๋ฐ๋ผ ๋ค์ด๋ฐ ์คโฆ
- ๊ตฌ์ฑ
- Object
- ์ ์ฅํ ๊ฐ ์์ฒด (์ด๊ธฐ ๊ฐ ์ง์ ํ์.)
- Object state change functions
- Update - ๋ณ๊ฒฝํ ๊ฐ ์ธํ
- Delete - ์ด๊ธฐ ๊ฐ์ผ๋ก ๋ค์ ์ธํ
- Ect Functions - ์ถ๊ฐ์ ์ธ Functions
- Object
example
import { Schedule } from '@typings/Schedule'
import { create } from 'zustand/react'
interface ScheduleStore {
schedules: Schedule[]
setSchedules: (schedules: Schedule[]) => void
addSchedules: (schedule: Schedule) => void
deleteSchedules: (id: number) => void
modifySchedules: (id: number, schedule: Schedule) => void
}
const useScheduleStore = create<ScheduleStore>(set => ({
schedules: [],
setSchedules: schedules => set({ schedules }),
addSchedules: schedule => set(state => ({ schedules: [...state.schedules, schedule] })),
deleteSchedules: id =>
set(state => ({ schedules: [...state.schedules.filter(schedule => schedule.id != id)] })),
modifySchedules: (id, schedule) => {
set(state => ({
schedules: state.schedules.map(stateSchedule =>
stateSchedule.id == id ? schedule : stateSchedule,
),
}))
},
}))
export default useScheduleStoreUsage
- ๊ด๋ฆฌ ํฌ์ธํธ๋ฅผ ์๋น์ค ๋ก์ง์ ๊ฐ์ ์ํค๊ธฐ ์ํด์ modelView์์๋ง ์ฌ์ฉ ๊ฐ๋ฅ.
- ์ด์ธ์ ์ฌ์ฉ์ฒ์์๋ modelView์์ ๋ฆฌํด ์์ผ์ค ๊ฐ์ ๊ฐ์ ์ ์ผ๋ก ์ฌ์ฉํด์ผํจ.
- ์ด๊ธฐ ๊ฐ์ ๋น๋๊ธฐ๊ฐ ํ์ํ ๊ฒฝ์ฐ์๋
null๋๋[](๋น array)๋ก ์ด๊ธฐํํ๊ณ modelView์์init() function์ ํตํด ๋ค์ ํ ๋น. - selector๋ฅผ ํตํด ๊ฐ์ ๋ฐ์ธ๋ฉ ํด์ผ ํจ.
- selector๋ก ํ๋ฉด์ ํ์ํ state๋ฅผ ์ง์ ํจ์ ๋ฐ๋ผ ํด๋น state๊ฐ ๋ณํ๋ ์์ ์๋ง ๋ฆฌ๋ ๋๋ง ๊ฐ๋ฅ.
- ๋ง์ ๊ฐ์ selector๋ฅผ ํตํด ๊ฐ์ ธ์ ๋ถํด ํ ๋นํ ๊ฒฝ์ฐ, useShallow๋ก ์์ ๋น๊ต๋ฅผ ํด์ผ ๋ถํ์ํ loop๊ฐ ๋ฐ์ํ์ง ์์.
- store์ ๊ฐ์ BE์์ ์ ๋ฌํด์ค ๊ฐ ์์ฒด๋ฅผ ์ ์ฅํ๊ฑฐ๋ FE์์ ์ฌ์ฉํ๊ธฐ ํธํ ์์ ๊ฐ์ผ๋ก ์ ์ฅํ๊ธฐ ๋๋ฌธ์ ํ๋ฉด์์ ๋ค๋ฅธ format์ด ํ์ํ ๊ฒฝ์ฐ, useMemo๋ฅผ ํตํด format์ ๋ณ๊ฒฝํ์ฌ ์ฌ์ฉํด์ผํจ.
- ๊ผญ ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋๋ผ๋ฉด store์ ๊ฐ์ ๋๋๋ก ๋ณ๊ฒฝํ๋ฉด ์๋จ.
example
import calendarRepository from '@repositories/CalendarRepository'
import { useMemo } from 'react'
import { Calendar } from '@typings/Calendar'
import dateFormatUtil from '@utils/date/dateFormatUtil'
import { ScheduleOfDate } from '@typings/ScheduleOfDate'
import scheduleRepository from '@repositories/ScheduleRepository'
import useCalendarStore from '@stores/useCalendarStore'
import useScheduleStore from '@stores/useScheduleStore'
import { useShallow } from 'zustand/react/shallow'
import useCalendarSelectStore from '@stores/useCalendarSelectStore'
import { scheduleType } from '@typings/constants/ScheduleType'
const useMonthlyCalendarViewModel = () => {
const currentDate = useCalendarSelectStore(useShallow(state => state.currentDate))
const { calendar, setCalendar } = useCalendarStore(
useShallow(state => ({
calendar: state.calendar,
setCalendar: state.setCalendar,
})),
)
const { schedules, setSchedules } = useScheduleStore(
useShallow(state => ({
schedules: state.schedules,
setSchedules: state.setSchedules,
})),
)
const { stringToDate } = dateFormatUtil
const calculatedMonthlyCalendar: null | Calendar = useMemo(() => {
if (!calendar) return null
const copyCalendar: Calendar = Object.assign(calendar)
const schedulesOfDate = schedules
.sort(a => (a.type == scheduleType.TASK ? 1 : -1))
.sort((a, b) => (stringToDate(a.startedAt).isAfter(stringToDate(b.startedAt)) ? 1 : -1))
.map((schedule, index) => schedule.getScheduleOfDateList(index + 1))
.flatMap(schedules => schedules)
let prevSchedules: ScheduleOfDate[] = []
copyCalendar.dates.forEach(date => {
const resultSchedules: ScheduleOfDate[] = []
const targetSchedules: ScheduleOfDate[] = schedulesOfDate.filter(
schedule =>
schedule.year == date.year && schedule.month == date.month && schedule.day == date.day,
)
let prevIndex = 0
// ๋น ์์ null ์ธํ
=> ํ๋ฉด์์ ์ฌ์ฉ ํ ๊ฒฝ์ฐ, null ๊ฐ์ ๋ํ ๋์ ํ์.
targetSchedules.forEach(schedule => {
const prevScheduleIndex = prevSchedules.findIndex(
targetSchedule => targetSchedule != null && targetSchedule.id == schedule.id,
)
for (let i = prevIndex; i < prevScheduleIndex; i++) resultSchedules.push(null)
prevIndex = prevScheduleIndex + 1
})
// ์ผ์ ์ธํ
targetSchedules.forEach(schedule => {
const prevScheduleIndex = prevSchedules.findIndex(
targetSchedule => targetSchedule != null && targetSchedule.id == schedule.id,
)
if (prevScheduleIndex != -1) {
resultSchedules[prevScheduleIndex] = schedule
} else {
const nullIndex = resultSchedules.findIndex(targetSchedule => targetSchedule == null)
if (nullIndex != -1) {
resultSchedules[nullIndex] = schedule
} else {
resultSchedules.push(schedule)
} }
})
prevSchedules = resultSchedules
date.schedules = resultSchedules
})
return copyCalendar
}, [calendar, schedules])
const setMonthlyCalendar = async () => {
setCalendar(null)
setSchedules([])
const monthlyCalendar = await calendarRepository.getMonthlyCalendar({
year: currentDate.year,
month: currentDate.month,
})
const scheduleList = await scheduleRepository.findByDate({
year: currentDate.year,
month: currentDate.month,
})
setCalendar(monthlyCalendar)
setSchedules(scheduleList)
}
const init = async () => {
console.log('init!!')
await setMonthlyCalendar()
}
return {
calculatedMonthlyCalendar,
currentDate,
init,
}
}
export default useMonthlyCalendarViewModel