[React Redux] redux의 state와 Modal(1)

bluejoy·2021년 12월 5일
1

React

목록 보기
3/19
post-thumbnail

글을 쓰게된 이유

제작 중인 프로젝트에서 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 상태 구성하기 - 공식문서

그러면 안되는 것은 아니지만 Redux의 핵심 설계 중 하나인 store안의 state의 지속성과 재수화(rehydration, 대체?)가 불가능해 time travel debugging을 사용할 수가 없게 된다(redux-devtools). Redux를 사용해야할 이유가 적어지는 것이다.

redux-persist 동작 원리 - rehydration에 대해 알려줌!

그렇다면 어떤 값이 state로?

Redux는 plain serializable objects(적절한 용어를 못찾음..)와 arrays, 원시 값들을 store에 저장하기를 매우 권장한다.

직렬화와 역직렬화

리덕스에 데이터를 넣기 위해 고민해야할 규칙

  • 다른 컴포넌트에서도 이 데이터를 사용하는지?
  • 원본 데이터에서 여러 데이터가 파생되어 사용되야 하는가?
  • 같은 데이터가 여러 컴포넌트에서 사용되는지?
  • 특정 시점으로 데이터를 바꿔 디버깅해야하는지? (예를 들어 time travel debugging - Redux DevTools)
  • 데이터 캐싱이 필요한가? (예를 들어, 의존하는 상태가 아닌 경우에는 업데이트를 하지 않는다.)
  • 컴포넌트가 다시 로드되는 동안 데이터를 일관되게 유지해야 하는가?(업데이트하며 상태가 손실되는 경우)

++ 리덕스에서는 앱 전체에서 필요한 전역 상태만 리덕스 스토어에 저장해야한다. 한 곳에서만 필요한 상태는 컴포넌트에서 관리되어야 한다.

그렇다면 어떻게?

고치는 과정은 다음에 쓰겠다.

참고 자료

profile
개발자 지망생입니다.

0개의 댓글