본문 바로가기

공부일지/Project

비전공자의 프로젝트 만들기) 스케줄 프로젝트 만들기 - part4 스케줄 수정작업

728x90
반응형

스케줄 프로젝트 만들기 - part4

 

와........ 이제부터 진짜 본격적인 개발을 한다고 생각이 되었다...

오류, 오류,,, 오류 끝나면 또 오류,,,,,,,,,,,

 

리액트 공부하면서 처음 보는 오류를 만났다...

와 씌............. 이건 뭐야 왜 렌더링이 많이 된다고 하는 거지 나는 데이터를 한 번밖에 보내지 않는데.....

 

수정하기 위해 기존 데이터를 가져왔는데 렌더가 너무 많이 된다고 하는 이런 오류는 참....

 

데이터를 가져와서 콘솔을 찍어보면 잘 나왔다.

 

하지만 그 데이터를 state에 넣는 순간 오류가 생기는데 일단 그러면 modal페이지에서 데이터를 가져와야 되는 건가?? 흐음...

 

작장 1~2시간을 걸쳐서 여러 방법을 사용한 결과... 해결법을 너무 쉬웠다... 혼자 Callback도 사용해 보고 데이터 받는 방식도 변경해 보고 state를 object로 변경해보고 했는데 UseEffect를 사용하니 해결되었다.

 

    useEffect(() => {
        if(editMode){
                setScheduleTitle(editData.title)
                setCrrentDate(format(new Date(editData.date), "yyyy-MM-dd"))
                setCurrentTime(format(new Date(editData.date), "HH:mm"))
                setscheduleCnt(editData.content)
                setIsChecked(editData.isComplate)
        }
    }, [modalOpen])

editMode가 true면 state에 edit데이터를 변경해주라는 이벤트였다.

modalOpen으로 팝업창이 오픈 될때마다 판단하고 실행하도록 해서 바로 적용되었다. 

이번 오류를 작업하면서 알았던것은 prop으로 받은 데이터보다 state가 빠르게 적용되는지 state에서 삼항으로 editData가 있으면 editData를 사용하고 없으면 빈값을 사용하도록 하였는데 무조건 빈값으로 적용되는 걸 보고 우선순위에 대해 알게 되었다.

 

useEffect가 정확히 맞는 해결방법인지는 잘 모르겠지만 일단 기능은 작동을 하니 한걸을 내디딘 거 같아 기분이 너무 좋다.

 

이제 EDIT 리듀서를 이용해 수정된 내용을 다시 저장하는 기능을 작업할 거예요.

 

이 글을 쓰면서 개발 작업을 진행 중이라 수정기능을 완성하게 되면 다시 글을 이어서 작성할 거 같아요.

 

그럼 EDIT 기능을 작업하고 다시 글을 작성할게요~~

 

드디어 EDIT까지 작업을 완료하고 왔습니다.

 

reducer/schedule.js

 

let keyId = 0


const currentSchedule = {
    scheduleList:[],
}

export const ADD = "ADD_SCHEDULE";
export const DELETE = "SCHEDULE/DELETE";
export const EDIT = "EDIT_SCHEDULE";
export const SUCCESS = "SCHEDULE/SUCCESS";


export const add_schedule = ({title, date, content, isComplate}) => {
    return{
        type:ADD, 
        scheduleList:{
            keyId:keyId++,
            title,
            date,
            content,
            isComplate
        }
    }
};

export const edit_schedule = ({keyId, title, date, content, isComplate}) => {
    console.log()
    return{
        type:EDIT,
        scheduleList:{
            keyId,
            title,
            date,
            content,
            isComplate
        }
    }
};


const schedule = (state = currentSchedule, action) => {
    switch(action.type){
        case ADD :
            return {
                scheduleList : [...state.scheduleList, action.scheduleList]
            }
        case EDIT :
            return {
                scheduleList : [...state.scheduleList.slice(0, action.scheduleList.keyId), action.scheduleList, ...state.scheduleList.slice(action.scheduleList.keyId + 1) ]
            }
        default :
        return state
    }
}

export default schedule;

사실 edit부분 작업이 오래 걸린 건 아니다.

 

수정 부분은 보면 ADD 기능과 받아오는 데이터는 같아서 동일하게 데이터를 받아 온다음 switch 쪽에서 이제 해당 데이터를 다시 업데이트해주는 코드를 작성하였다.

 

업데이트를 해주기 위해 keyId기준으로 slice를 사용해서 기존 state의 배열에서 0번째부터 데이터 업데이트 데이터 앞까지 잘라서 넣고 수정코드를 넣고 기존 수정코드 이후 코드부터 끝의 코드까지 다시 넣어주는 방식으로 했다.

제가 글재주가 많이 없어서 이해가 조금 어렵다고 느껴질 수 있을 것 같은데 조금이라도 쉽게 설명드리면 나는 keyId가 1번인 데이터를 수정하고 업데이트를 해주려고 한다고 1번 전인 0번의 데이터는 그대로 넣어주고 수정된 1번을 추가하고 나머지 1번 이후 데이터들을 그대로 다시 추가해주는 방식이다.

 

slice가 배열이 바로 수정되는 게 아니라 해당 배열을 수정한 뒤 새로운 배열을 만든다고 한다 그래서 스프레드(전개 연산자)를 사용해서 기존배열의 데이터를 없애고 새로운 배열을 넣어주었다.

 

그리고 어찌 보면 시간이 제일 오래 걸린 데이터 전송시 오류 체크하는 부분이다.

 

오래걸린 이유는 내가 사용한 semantic-ui-react의 error의 기능을 찾는데 오래 걸린 거 같다. 

그냥 코드 안에 error을 넣어서 사용할 수도 있는데 처음 사용해 본 라이브러리이기도 하고 뭔가 다양한 예제를 찾고 싶었는데 생각보다 다양한 예제는 없었던 거 같다.

 

그럼 modalPop의 에러 체크 코드를 보여드리자면

    //에러체크
    const [dataError, setDataError] = useState({})
    
        const dataChecked = () => {
        if(!scheduleTitle || !currentDate){
            if(!scheduleTitle && !currentDate){
                setDataError({title:false, date:false});
            }else if(!scheduleTitle){
                setDataError({title:false});
            }else if(!currentDate){
                setDataError({date:false});
            }
            return false
        }
        return true
    }

    useEffect(() => {
        if(Object.keys(dataError).length > 0){
            if(scheduleTitle.length > 0){
                setDataError({title:true});
                console.log(dataError)
            }
            if(currentDate.length > 0){
                setDataError({date:true});
                console.log(dataError)
            }
        }
    }, [scheduleTitle, currentDate])

    const handleAddSchedule = () =>{

        if(dataChecked()){
            if(!editMode){
                dispatch(add_schedule({
                    title:scheduleTitle,
                    date:new Date(`${currentDate} ${currentTime}`),
                    content:scheduleCnt,
                    isComplate:false
                }))
            }else{
                dispatch(edit_schedule({
                    keyId:editData.keyId,
                    title:scheduleTitle,
                    date:new Date(`${currentDate} ${currentTime}`),
                    content:scheduleCnt,
                    isComplate:isChecked
                }))
            }
            setModalClose()
        }
    }

혼자 이것저것 삽질을 많이 해서 얻은 결과물이다. 

 

솔직히 해당 방식이 완벽하고 깔끔하다고는 생각하지 않지만 지금 현재 내가 경험했던 방식으로는 해당 방법이 최선인 거 같다.

 

처음에는 각각 오류를 체크하려고 했는데 굳이 그러면 state를 너무 많이 만들어서 사용해야 될 거 같아서 안되고 기존 state를 이용하려고 했는데 그러면 value 쪽이 이상해지고 해서 그냥 어차피 내가 받아야 되는 오류 체크는 2가지밖에 안되니 객체형태의 state를 만들어서 거기에 해당 오류가 있을 때 만들자 라는 생각을 했다.

 

그래서 타이틀과 날짜가 둘 다 없으면 둘다 오류를 표시하고 둘 중 하나만 오류일 때는 해당 부분을 찾아서 오류를 체크했다.

그리고 useEffect를 사용해서 title과 date가 변경이 포착되었을 때 작동하고 해당 effect도 if문을 사용해서 dataError의 object에 key값이 하나라도 있을 때 실행되게 하였다.

<Form.Field
    id='form-input-control-title'
    control={Input}
    placeholder="제목"
    value={scheduleTitle}
    transparent
    onChange={(e)=>setScheduleTitle(e.target.value)}

    error={dataError.title === false && {
        content: '제목을 입력해 주세요.',
        pointing: 'below',
    }}
/>


<Form.Field
    id='form-input-control-date'
    readOnly
    control={Input}
    placeholder={format(new Date(), "yyyy-MM-dd")}
    value={currentDate}
    icon={<Icon name="calendar" alternate="true" outline="true" />}
    transparent
    error={dataError.date === false && {
        content: '날짜를 입력해 주세요.',
        pointing: 'below',
    }}
/>

태그도 input에서 from태그로 변경해서 작업하였다.  그래야 내가 원하는 error표출 디자인이 출력되었다.

dataError에서 title이 false이면 error가 표시되고 true면 표시 안 되는 방식으로 작업했으며 날짜도 동일하게 작업하였다.

 

내가 원하는 error표출 디자인이 작업 완료 되었다.

 

휴.... 드디어 add와 edit를 작업하였다.

이제 남은 건 VIew와 Delete만 남은 거 같다.

 

내가 생각했을 때 제일 어려운 reducer와 기본 틀을 만드는 작업은 어느 정도 끝났기 때문에 View와 Delete는 생각보다 오래 걸리진 않겠지??

 

다음일지에는 두 가지 기능을 한 번에 다 적을 수 있었으면 좋겠다.

 

그럼 저는 나머지 기능을 작업하러 가볼게요~~

728x90
반응형