스케줄 프로젝트 만들기 - part2
저번일지에서 리덕스 설치 후 오류 수정하러 간다고 했던 MIN입니다.
오류를 수정하고 다시 돌아왔습니다.

하지만 아시죠... 오류를 수정하면 또 다른 오류가 나온다는 거를............ 나름 인강을 듣고 리덕스 쪽에 이해를 했다고 생각했던 제가 너무 안일했던 거 같네요... 상태관리... 아직은 저 같은 주니어한테는 어렵네요.
그럼 저번시간에 생겼던 오류가 무엇이냐면...
바로 리액트 18버전에서는 랜더링 하는 방식이 다른데 제가 무지성으로 블로그에 있는 글을 막 들고 와서 작성을 하는 바람에 생겼던 오류였더라고요..... 당연히 그 문제는 아닐 거라 생각해서 진짜 한시간 넘게 오류 찾았어요....
이번시간에도 리덕스 때문에 데이터가 안 받아지고 데이터 저장이 안 되고 하는 그런 우여곡절 끝에 세션 스토리지에 까지 저장하는 기능까지 작업하게 되었습니다.
그러면서 리덕스 action 페이지의 코드도 변경되었는데 한번 확인해 볼까요??
뭔가 혼자 이렇게 해놨다는 게 기뻐서 글 쓰면서 들떠 있는 게 느껴지네요 ㅎㅎ

아직까지도 일정등록 기능 밖에 없지만
/reducers/schedule.js
let keyId = 0
export const initalSchedule = ({title, date, content}) => {
return {
scheduleList:{
keyId:keyId++,
title,
date,
content
}
}
}
const currentSchedule = {
scheduleList:[],
}
export const ADD = "ADD_SCHEDULE";
export const DELETE = "SCHEDULE/DELETE";
export const EDIT = "SCHEDULE/EDIT";
export const SUCCESS = "SCHEDULE/SUCCESS";
export const add_schedule = ({title, date, content}) => {
return{
type:ADD,
scheduleList:{
keyId:keyId++,
title,
date,
content
}
}
};
const schedule = (state = currentSchedule, action) => {
switch(action.type){
case ADD :
return {
scheduleList : [...state.scheduleList, action.scheduleList]
}
default :
return state
}
}
export default schedule;
action 페이지의 코드가 몇 개 추가되고 몇 개는 없어졌습니다.
솔직히 이 action페이지 때문에 시간이 오래 걸렸었어요ㅠㅠ. 왜냐면 이것저것 해본다고 객체 타입으로도 저장해 보고 배열로도 저장해보고 function으로도 해보고 const, let 도 써보고 써봤지만 저한테는 지금 저 코드가 딱 알맞은 거 같더라고요.
add_schedule의 기능은 tppe:ADD 위에서 선언했던 타입을 들고 와 scheduleList라는 객체를 만들어서 저장하는 방식으로 했습니다.
아 글 쓰다 보니 initalSchedule 이 부분을 지우지 않았네요. 처음에는 저기에 받아온 데이터를 넣고 출력하는 방식으로 했는데 제가 원하는 데이터로 저장이 안 되고 조금 이상하더라고요.
그래서 아래의 add_schedule 코드로 변경해서 return도 스케줄 리스트에 기존 state의 리스트와 신규 리스트를 저장하는 방식으로 했습니다.
선배님들 조금 더 좋은 방식이 있으면 댓글로 알려주시면 감사드리겠습니다.

아 그러고 보니 index.js 파일은 제가 안 보여 드렸네요.
import React from 'react';
import ReactDOM from 'react-dom/client';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './App';
import { persistStore } from "redux-persist";
import { PersistGate } from "redux-persist/integration/react";
import persistReducer from "./reducers";
import 'semantic-ui-css/semantic.min.css'
import './index.css';
const store = createStore(persistReducer);
const root = ReactDOM.createRoot(document.getElementById('root'));
const persistor = persistStore(store);
const render = () => root.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById('root'),
);
render()
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
해당 코드는 이제 세션 스토리지까지 저장하는 방식을 추가한 코드입니다. 기존에는 createStore에는 rootReducer이 들어갔습니다.
Redux에 관해서 자세한 내용은 구글링 하니 많이 나오더라고요. 좋은 글들이 많아서 한번 참고해 보시는 거 추천드려요.
일정을 등록하는 Modal 페이지 코드 들이에요. 코드가 길어서 style 부분은 지우고 보여드려요.
import { format } from 'date-fns'
import React, { useState } from 'react'
import ReactDatePicker from 'react-datepicker'
import { useDispatch, useSelector } from 'react-redux'
import { Button, Divider, Form, Header, Icon, Input, Modal, TextArea } from 'semantic-ui-react'
import { styled } from 'styled-components'
import { add_schedule } from '../reducers/schedule'
const ModalPop = ({schedule}) => {
const dispatch = useDispatch();
const [modalPop, setModalPop] = useState(false)
//제목
const [scheduleTitle, setScheduleTitle] = useState('')
// 날짜
const [changeDate, setChangeDate] = useState('')
//내용
const [scheduleCnt, setscheduleCnt] = useState('')
const changDate = (e) =>{
return e && setChangeDate(format(e, "yyyy-MM-dd"))
}
const handleAddSchedule = () =>{
dispatch(add_schedule({
title:scheduleTitle,
date:changeDate,
content:scheduleCnt
}))
setScheduleTitle('');
setChangeDate('');
setscheduleCnt('');
setModalPop(false)
}
const setModalClose = () =>{
setScheduleTitle('');
setChangeDate('');
setscheduleCnt('');
setModalPop(false)
}
return (
<PopupBox>
<Modal
onClose={()=>setModalClose()}
onOpen={()=>setModalPop(true)}
open={modalPop}
trigger={<Button>일정 등록</Button>}
style={{width:"95%", maxWidth:"500px"}}
>
<Modal.Header style={{fontFamily:'SUITE-Regular', fontSize:'17px', padding:'15px 20px'}}>일정 등록</Modal.Header>
<ModalContainer>
<Form style={{padding:20, boxSizing:'border-box'}}>
<Modal.Content style={{display:'flex', gap:'20px', flexFlow:'row wrap', }}>
<Input transparent placeholder="제목" defaultValue={scheduleTitle} onChange={(e)=>setScheduleTitle(e.target.value)} />
<ModalCalendar>
<Input placeholder={format(new Date(), "yyyy-MM-dd")} readOnly transparent defaultValue={changeDate} icon={<Icon name="calendar" alternate="true" outline="true" />} />
<ReactDatePicker selected={new Date()} onChange={(date) => changDate(date)} />
</ModalCalendar>
<TextArea placeholder='내용' style={{ minHeight: 100, width:'100%' }} defaultValue={scheduleCnt} onChange={(e)=>setscheduleCnt(e.target.value)} />
</Modal.Content>
</Form>
</ModalContainer>
<Modal.Actions>
<Button color='black' onClick={() => setModalClose()}>취소</Button>
<Button
content="등록"
labelPosition='right'
icon='checkmark'
onClick={() => handleAddSchedule()}
positive
/>
</Modal.Actions>
</Modal>
</PopupBox>
)
}
export default ModalPop
dispath로 add 기능을 가져와서 각각 key와 value의 정보를 전달했어요.
아까도 말씀드렸지만 action부분 때문에 진짜... 여기 페이지도 썼다 지웠다 썼다 지웠다.
너무 많이 한 거 같아요.
값이 제대로 들어오는지 확인하기 위해 useSelect도 했는데 알고 보니 해당페이지에서 글등록 하고 바로 select을 console로 찍으니 안 나오더라고요.
렌더링 시키기 전에 콘솔을 보여줘서 그런가 싶더라고요. 아니라면 제가 더 공부해 보겠습니다.
항상 글을 작성하면서 새로운 방식이 떠오르네요 굳이 내용 초기화 되는 부분을 2개를 쓰지 않고 close를 handleAdd 쪽에 넣으면 초기화되면서 닫히겠네요.
이 방식도 글 작성 후 수정해야겠네요.
이제 세션에 저 정했던 데이터를 일자별로 해당 일자에 맞는 데이터를 출력시켜주기 위해 CalendarRow 페이지에서
CalendarItem이라는 컴포넌트를 하나 만들었어요.
CalendarItem
import { format } from 'date-fns'
import React from 'react'
import { useSelector } from 'react-redux';
import schedule from './../reducers/schedule';
const CalendarItem = ({itemDate}) => {
const schedulsDataList = useSelector(state => state.schedule.scheduleList);
const itemDataCnt = format(itemDate, "yyyy-MM-dd");
if(schedulsDataList.length > 0){
return(
schedulsDataList.map((schedule, i) => {
// eslint-disable-next-line no-lone-blocks
{
return(
schedule.date === itemDataCnt
? <li key={schedule.keyId}>{schedule.title}</li>
:''
)
}
})
)
}
}
export default CalendarItem
제가 적은 저 방식이 괜찮은 방식인지는 모르겠어요.
저는 개인적으로는 중간에 break를 할 필요가 없고 배열 타입이면 map을 사용하는 게 좋더라고요.
일정이 있으면 return을 시켜주고 그 일정이 days와 같은 날이면 출력시켜주는 방식으로 했어요.
CalendarRow
return (
<CalendarDaysBox>
{weekArray.map((week, i)=> (
<ul className='calendarBox__div days-div' key={i}>
{dayArray.map((day, idx)=> (
days = addDays(days -1 , 1),
<CalendarDays
key={idx}
className={
`days-div__content ${!isSameMonth(days, monthStart) ? 'ohterMonth' : ''} ${idx === 0 ? 'CalendarDays_sun' : idx === 6 ? 'CalendarDays_sat' : ''} ${Number(format(days, 'd')) === new Date().getDate() && Number(format(days, 'M')) === new Date().getMonth()+1 ? "calendarToday" : '' }`
}
>
<CalendarDay className='days-div__content__span'>
<span>{format(days,'dd')}</span>
<ul>
<CalendarItem itemDate={days} />
</ul>
</CalendarDay>
</CalendarDays>
))}
</ul>
))}
</CalendarDaysBox>
)
}
export default CalendarRow
Row 파일은 item 컴포넌트만 추가하고 날짜만 전달했어요.
글로 작성하니 간단한 기능들인 거 같은데 혼자 엄청 고생을 했는지.... 아직 취업의 길은 엄청 먼 거 같네요.
이럴 때는 왜 퍼블리싱만 하고 프런트로 빨리 전향을 안 했을까 하는 생각이 많이 드네요.....
예전에 프런트라는 개발자가 있는 걸 알았더라면 내가 IT 쪽에 관심이 더 많았더라면 오늘따라 조금 후회가 되네요
하지만 후회하면 얻는 게 없으니 더 많이 공부해서 빨리 프론트로 이직할 수 있게 노력하려고요.
오늘은 미래의 목표를 위한 한 걸음 이니깐요.

그럼 주말 잘 보내시고 다음 주 평일에 다시 올게요~~
'공부일지 > Project' 카테고리의 다른 글
비전공자의 프로젝트 만들기) 스케줄 프로젝트 만들기 - part4 스케줄 수정작업 (0) | 2023.06.02 |
---|---|
비전공자의 프로젝트 만들기) 스케줄 프로젝트 만들기 - part3 날짜 작업 (0) | 2023.05.31 |
비전공자의 프로젝트 만들기) 스케줄 프로젝트 만들기 - part1 오류의 위기 ...... (2) | 2023.05.26 |
비전공자의 프로젝트 만들기) Disneyplus App 만들기 part4 (0) | 2023.05.23 |
비전공자의 프로젝트 만들기) Disneyplus App 만들기 part3 (0) | 2023.05.23 |