이전 포스팅에서는 자식(Header) -> 부모(Calendar) -> 자식(Body)으로 데이터를 전달했다. 그런데 useState를 이용해 데이터를 변화시켜도, 마지막 자식 컴포넌트(Body)에서 리렌더링 되지 않는 문제가 발생했다. 이를 해결하지 못해, redux를 사용해보기로 마음먹었다.
여러가지 자료를 참고해 index.js에 store를 세팅했다.
state.baseDate.date를 호출해야 한다.state.date로 Moment 객체를 불러와 변경하는 방식을 택했다. import { createAction, handleActions } from "redux-actions";
import moment from "moment";
const DEC_MONTH = "baseDate/DEC_MONTH";
const INC_MONTH = "baseDate/INC_MONTH";
export const decMonth = createAction(DEC_MONTH);
export const incMonth = createAction(INC_MONTH);
const initialState = {
date: moment(),
}
export default handleActions(
{
[DEC_MONTH]: (state, action) => ({
...state,
baseDate: state.date.add(-1, 'months'),
}),
[INC_MONTH]: (state, action) => ({
...state,
baseDate: state.date.add(1, 'months'),
})
},
initialState
);
src/store/modules/baseDate.js에 DEC_MONTH와 INC_MONTH를 정의했다.import React, { useState, useEffect, useCallback } from "react";
import moment from "moment";
function Calendar(props) {
const baseDate = useSelector((state) => state)
const curDate = baseDate.baseDate.date.clone()
const viewMonth = curDate.format('YYYY - MM')
const baseDate = useSelector((state) => state)
const curDate = baseDate.baseDate.date.clone()
const firstDateOfMonth = curDate.clone().startOf('month')
const firstDayOfMonth = firstDateOfMonth.get('d')
const firstDate = firstDateOfMonth.clone().add(-firstDayOfMonth, 'days')
clone()을 이용했다.state.baseDate.date를 꺼내 줄 수도 있지만, 이 경우 store의 state가 변경되더라도 이를 인식하지 못해 리렌더링이 되지 않는 상황이 발생했다. state를 모두 받아줄 경우는 무사히 리렌더링 된다.import { useDispatch, useSelector } from 'react-redux';
import * as actions from "../../store/modules/baseDate";
const dispatch = useDispatch();
const decMonth = useCallback(() => {
dispatch(actions.decMonth());
}, [dispatch])
const incMonth = useCallback(() => {
dispatch(actions.incMonth());
}, [dispatch])
useDispatch와 useCallback을 이용했다. return (
<div className="calHeaderWrapper">
<div className="calHeaderBtn calHeaderBeforeBtn">
<LeftOutlined
style={{ color: "#EFBF43"}}
onClick={() => {
decMonth();
}}
/>
</div>
<div className="calHeaderNow">
{ viewMonth }
</div>
<div className="calHeaderBtn calHeaderAfterBtn">
<RightOutlined
style={{ color: "#EFBF43"}}
onClick={() => {
incMonth();
}}
/>
</div>
</div>
);
Header의 버튼을 클릭할 경우 store의 state가 변경되며, 이에 따라 Header와 Body 컴포넌트에서 state를 받아주는 모든 값이 성공적으로 리렌더링 된다.
