이전 포스팅에서는 자식(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를 받아주는 모든 값이 성공적으로 리렌더링 된다.