제작 중인 프로젝트에서 Modal을 직접 제작하는 중이였다. 공통적으로 사용되는 Modal 배경을 전역에 만들어 놓고 Modal의 표시 여부와 내부 content를 Redux State
로 만들어서 작동시키겠다는 생각이였다.
문제는 content를 React Element
를 Redux의 State로 직접 넣어서 구현을 한 것이다. 작동에는 문제가 없었지만 곧 문제가 생겼다. 문제가 생긴 코드는 아래 코드와 같은 구조였다.
React Element와 Component 차이
최상단 App.js
import React, {useState} from 'react';
import ReactDOM from 'react-dom';
import {connect} from 'react-redux';
import {show} from './store/reducers/modal';
import Modal from './components/modal';
const App = ({isVisible, show}) => {
return (
<>
<button onClick={()=>{show('search');}}>Redux로 검색창 열기</button>
<Modal/>
</>
)
}
const mapStateToProps = (state) => ({
isVisible: state.modal.isVisible
});
const mapDispatchToProps = (dispatch) => ({
show: (content) => dispatch(show({content})),
});
export default connect(mapStateToProps,mapDispatchToProps)(App);
최상단에서 렌더링되는 modal.js
import React from 'react';
import {connect} from 'react-redux';
import {drop} from '../store/reducers/modal';
import {useEffect} from 'react';
import * as modals from './modals';
import styles from './modal.module.css'
const Modal = ({isVisible, content, drop}) => {
const checkEsc = (e) => {
if (e.code == 'Escape')
drop();
}
const Content = modals[content];
useEffect(()=>{
if(isVisible)
{
window.addEventListener('keydown', checkEsc);
}
else
window.removeEventListener('keydown',checkEsc);
return ()=>{window.removeEventListener('keydown',checkEsc)};
}, [isVisible])
return (
<>
{isVisible &&
<div className={styles.modalContainer}>
<div className={styles.closeBar}>
<button onClick={drop}>XXXX</button>
</div>
<Content drop ={drop} />
</div>}
</>
);
}
const mapStateToProps = (state) => ({
isVisible: state.modal.isVisible,
content: state.modal.content
});
const mapDispatchToProps = (dispatch) => ({
drop: () => dispatch(drop()),
});
export default connect(mapStateToProps, mapDispatchToProps)(Modal);
content는 검색을 받는 컴포넌트였다. content에서 검색 버튼을 누르고 나면 Modal이 닫히게 하기 위해 drop 기능을 하는 함수를 prop으로 내려주려고 했다. React Element
에는 prop
을 넘기는 법을 몰라 검색을 하다가 이렇게 React 구성 요소
를 Redux State
에 저장하는 것은 권장하지 않는다는 글을 보게 되었다. (나중에 찾긴 했는데 내 방식대로 굳이 해결을 하자면 React Component
를 넘기면 되긴한다.)
그러면 안되는 것은 아니지만 Redux의 핵심 설계 중 하나인 store안의 state의 지속성과 재수화(rehydration, 대체?)가 불가능해 time travel debugging
을 사용할 수가 없게 된다(redux-devtools
). Redux를 사용해야할 이유가 적어지는 것이다.
redux-persist 동작 원리 - rehydration에 대해 알려줌!
Redux는 plain serializable objects
(적절한 용어를 못찾음..)와 arrays, 원시 값들을 store에 저장하기를 매우 권장한다.
++ 리덕스에서는 앱 전체에서 필요한 전역 상태만 리덕스 스토어에 저장해야한다. 한 곳에서만 필요한 상태는 컴포넌트에서 관리되어야 한다.
고치는 과정은 다음에 쓰겠다.