React 기초 정리 6편

정인아·2022년 6월 30일
0

기초 정리 6편으로 돌아왔습니다.
기초 정리가 얼마나 길어질지는 모르겠지만, 제 힘이 닿는한 계속 작성 해보려 합니다.
나중에는 제가 이 정리편을 보고 복습할 수 있다는 마음으로 최대한 자세히, 그리고 간단한 코드 예제로 정리 해볼겁니다.

오늘은 ref와 portal에 대해 공부 하려합니다.

그전에, 저희가 쓰는 JSX의 문제점을 몇가지 살펴 봅시다.

위와 같은 JSX문법이 있습니다. 저는 h2태그와 p태그를 이용하여 해당 html을 반환하고 싶습니다.

이미지에서 보시면 이미 눈치 채셨겠지만, 오류가 뜹니다.
이 인접합 두 JSX는 다른 JSX요소에 의해 래핑되지 않았습니다.
이는 리액트가 허락하지 않습니다.
왜냐하면 JSX문법에서는 루트 JSX요소는 1개여야합니다.

말이 어렵죠.
무슨 말이냐면 한 컴포넌트는 하나의 HTML을 반환해야합니다. 그안에 어떤 자식이 있는지는 상관없지만 최상위 부모는 하나여야 하는거죠.

그 이유는 간단합니다.
해당 JSX문법을 자바스크립트로 변환 하게 되면, 자바스크립트에서는 둘 이상을 반환할 수 없습니다.

	return(
    	React.createElement("h2", {}, "title");
        React.createElement("h", {}, "텍스트를 작성");
    );

위 와같이 말이죠.

그럼 이를 해결하기 위해서 방법은 하나입니다.
부모를 만드는 것이죠.

아마 많은 분들이 div 태그를 생각하실겁니다.
나쁘진 않습니다. 그리고 다른 태그도 생각할 수 도 있죠.
그러나, 쓸데없는 태그를 계속 감싸야하고, 시멘틱 태그에 맞지도 않을테죠.

물론 다른 방법도 있습니다.

Wrapper라는 컴포넌트를 하나 만들어 줍니다.

여기서 props.children은 무엇일까요?

props는 저희가 배운적이 있습니다.

부모의 컴포넌트가 자식의 컴포넌트로 데이터를 보내는 겁니다.
근데 데이터만 보내는게 아니라는 뜻이죠.

children은 말그대로 자식입니다.
즉, Wrapper 컴포넌트에 감싸진 자식을 뜻합니다.
Wrapper로 감싸면 그 자식 컴포넌트도 감싸는 겁니다.

이렇게 말이죠.

그런데 리액트가 이 Wrapper를 아예 내장시켜줬습니다.
바로 React.Fragment입니다.
리액트에서 제공하는 프래그먼트로 해당 이슈를 한방에 해결해줍니다.

위와 같이 말이죠.
원래는 Wrapper를 import해왔지만, 그 줄이 하나 줄었습니다.

더 간단한 방식을 알려드릴까요?

아예 아무 것도 적혀있지 않은 태그로 감쌉니다.

이젠 아예 React 조차 import하지 않습니다.
<></> 태그가 프래그먼트와 동일한 역할을 합니다.

portal

서비스 페이지를 작업하다보면, 모달창 작업을 해야하는 경우가 많이 일어납니다.
저희가 html, css, js로 프로젝트를 진행했을 경우, 모달창 작업을 어떻게 하셨나요?

아마 모달 관련된 HTML을 제일 하단이나 상단에 놔두고, display: none으로 처리했을겁니다.

리액트로 작업을 하게 되면, 모달 컴포넌트를 만들고 이 모달창이 필요한 컴포넌트에 작업 하게 될겁니다.

	return (
    	<>
          <Modal />
          <Section />
    	</>
    )

위 와 같이 말이죠. 그럼 배포 후, 개발자 모드로 요소를 보게 된다면

	<div id="root">
    	<div class="modal"> **** </div>
        <form> *** </form>
    </div>

위 와 같이 보일 겁니다.
위의 코드는 정상 작동 할겁니다. 하지만 모달이 여러개가 존재 한다면 어떨까요?

이상하죠?
모달창은 페이지 젤 위로 보여야하는 오버레이여야합니다.
모두 비슷하게 작업하시겠지만, 저는 모달창의 제일 부모 태그를 absolute를 주고, width와 height를 100%로 줍니다.
그리고 background- color 로 약간 어둡게 만들죠.

그리고 그 안에 모달 스타일링 작업을 합니다.

js로 많은 이벤트를 컨트롤 할 수 있습니다.
그렇지만, 정상 작동 한다고 전부가 아닙니다.
클린한 코드가 아닌거죠.
그래서 항상 코드 한줄 한줄에 의미가 있어야 한다고 생각합니다.
그렇기에 모달창도 의미에 맞게 작업을 하는게 중요합니다.

리액트의 코드는 변화하지 않지만
html로 렌더링 돼었을때 DOM에서는 정상적인 코드 방식으로

    <div class="modal"> **** </div>
    <div id="root">
        <form> *** </form>
    </div>

위 와 같이 렌더링하게 할 수 있습니다.
이 때 필요한 개념이 portal입니다.

위의 예시 코드를 보시면 div의 id값이 root 인것을 볼 수 있습니다.
리액트는 js코드만 가지고 해당 div 태그에 렌더링 하는 형식으로 작동합니다.

그런데 어떻게 root 태그를 벗어나서 modal을 작성 할 수 있을까요?

portal을 사용하기 위해 두가지가 필요합니다.
해당 컴포넌트를 옮길 장소가 필요합니다.
그리고 컴포너트에게 그 장소로 portal을 가져야 한다고 선언해야 합니다.

먼저 /public/index.html 파일로 가서

위와 같이 div 태그를 추가 해줍니다.

그리고 Modal 컴포넌트에서

위와 같이 작업 해줍니다.
react-dom이라는 라이브러리가 이미 portal을 만들어주는 함수를 가지고 있습니다.
저희는 첫번째 인자로 모달 컴포넌트를, 두번째 인자로는 해당 DOM을 넣어줍니다.
여기서 중요한건 그냥 id값이 아닌 DOM을 넣어주여하기에 DOM API를 사용했습니다.
마치 index.js에 App 컴포넌트를 렌더링 하는 형태와 굉장히 유사합니다.

위와 같이 사용한다면 모달을 어디서든 사용가능합니다.

실은 제가 회사에서 프로젝트를 작업할 때, 모달창을 위와같이 작업해야하지만 퍼블팀에서 react-modal이라는 라이브러리를 사용하여 모달창을 구현해줬습니다.
해당 라이브러리가 위와 같은 작업을 저희 대신 해줘서 모달작업을 편하게 했던 기억이 납니다.
해당 라이브러리 사용도 추천드립니다.

제가 현재 너무 무리하게 개인 프로젝트 일정을 잡다보니 (혼자서 3개 정도 진행합니다... 진도도 안나가요ㅜㅜ)
블로그 포스팅이 굉장히 늦어지네요.
앞으로 일주일에 포스팅 한개를 목표로 꾸준히 올려보겠습니다.

긴 글 읽어주셔서 감사합니다.

다음편에는 ref와 useEffect에 관한 정리로 돌아오겠습니다!!

profile
프론트엔드 개발자

0개의 댓글