본문 바로가기
Lesson

React 완벽 가이드 Session 9

by bmodel 2022. 8. 3.

JSX 제한 사항 및 해결 방법

JSX 제한사항

리액트에서 루트 JSX요소는 한 개여야한다..

해결법은 최상위 태그로 무언가 하나를 만들어서 children으로 넣는것이다.

JSX에는 하나를 초과하는 "root" JSX요소를 리턴 할 수 없는 한계점이 있다.

이것은 리액트 자체의 문제가 아니라 JS에서 둘 이상을 리턴 할 수 없어서 발생하는 문제이다.

그림처럼 JSX 코드는 React.createElement로 변환되기 때문에 하나만 사용 할 수 있는 것이다

해결방법

인접한 요소들을 div로 감싸면 된다.

반드시 div여야만 되는 것은 아니고 컴포넌트도 가능하다.

이렇게 div로 감싸는 방식을 선택하게 됐을때 div soup라고 불리는 새로운 문제가 발생하게 된다.

실제 DOM으로 렌더링 될 때 리액트 컴포넌트가 많이 중첩 될 수가 있고 여러가지 이유로 그 컴포넌트들을 div로 감싸줘야 하는 경우가 생긴다.

JSX 한계사항 때문에 이러한 불필요한 div들이 실제 DOM으로 렌더링 되는데 시멘틱 웹적으로도 좋지 않고 웹 페이지 스타일링에도 문제를 발생시킬수 있으며 앱이 커졌을 경우 뚜렷한 성능저하로 연결되게 된다 .

 

컴포넌트 감싸기(wrapper) 만들기

// Wrapper.js
const Wrapper = props => {
  return props.children;
};

export default Wrapper;
// AddUser.js
<Wrapper>
      {error && (
        <ErrorModal
          title={error.title}
          message={error.message}
...
</Wrapper>

soup 문제를 해결하기 위해서는 이런식으로 Wrapper를 만들어줘서 씌워주면 된다.

(import 해주는거 잊지 말자)

이 Wrapper 컴포넌트는 그저 props.children을 return하기만 하는 빈 컴포넌트이다.

그럼에도 불구하고 JSX 제한요소는 잘 충족하기 때문에 정상적으로 렌더링된다.

개발자도구로 확인해보면 div로 감쌌을때와 다르게 렌더링 되지 않는걸 확인 할 수 있다.

 

리액트 조각

위에서 만든 Wrapper처럼 굳이 만들지 않아도 이미 리액트에 해당 기능이 존재하고 있다.
<React.Fragment></React.Fragment>를 사용하거나 <></>를 사용하면 된다.
empty wrapper의 경우에는 프로젝트 설정에 따라서 지원하지 않는 경우가 있지만 React.fragment를 쓰면 무조건 작동한다.

Fragment 컴포넌트

<React.Fragment>

<h2>안녕하세요</h2>

</React.Fragment>

 

 

리액트 포털 소개

이 코드의 문제가 무엇일까요?

모달은 전체페이지에 대한 오버레이이다. 코드가 오버레이임을 인식하지 못할 수 있다.

작동한다는 것 만으로 좋은 코드라고 할 수 없다. 의미론적인 관점에서

fragement를 사용하면 최종 페이지에 불필요한 HTML 요소들이 줄어든다.

 

해결법

리액트 포털이 있다.

오버레이 내용이 있는 모달이 깊게 중첩되면 안되는 문제를 포털을 사용하여 해결할 수 있다.

리액트 DOM은 브라우저에 대한 리액트용 어댑터의 일종이라 할 수 있다.

 

포털 작업하기

이 코드의 문제는 무엇일까요?

백드롭과 모달 오버레이에 대한 코드가 root안으로 랜더링 된다. 오버레이 안에 있는 모달이 깊게 중첩되는 문제가 있다.

 

해결법

modal 컴포넌트는 html 요소의 가장 위에 오도록 해야한다.

body의 직계자식으로 하기 위해서

  1. index.html에서 div태그 구조를 만들어 준다.
  2. 끌어올릴 컴포넌트에서 리액트 돔을 불러온다.
  3. createPortal을 이용하여 컴포넌트를 끌어올린다.

포털을 위해서는 두가지가 필요한데 한가지는 컴포넌트를 이동시킬 장소이고 다른 한가지는 컴포넌트에게 그곳에 포털을 가져가야 한다고 알려줄 필요가 있다.

현재 이런식으로 Backdrop과 ModalOverlay가 하나의 컴포넌트에 들어가 있는데 이걸 적절하게 수정해야 한다.

 

"ref"로 작업하기

ref

참조(reference)의 줄임말이고 매우 강력한 도구이다.

가장 기본적인 기능은 DOM에 직접 접근해서 작업을 할 수 있게 하는것이다.

하지만 dom의 요소들을 변경하는 것은 지양해야한다. 보통은 값을 빠르게 읽어오고 싶을 때 사용

 

1) 사용 방법

  • useRef를 import 한다.
import { useRef } from "react";

 

  • ref로 받아올 변수 선언
const nameInputRef = useRef();
const ageInputRef = useRef();
  • form 태그에서 ref로 dom 요소를 접근시에 아래처럼 사용
<form onSubmit={addUserHandler}>
    <input id="username" type="text" ref={nameInputRef} /><input id="age" type="number" ref={ageInputRef} /><Button type="submit">Add User</Button>
</form>
  • ref로 선언한 변수는 객체를 반환한다.

그리고 변수이름.current.(실제 돔에서 사용되는 속성) 으로 접근 가능

const enteredName = nameInputRef.current.value;
const enteredUserAge = ageInputRef.current.value;

state나 ref 둘 중 적합한 방식으로 선택하여 사용하면 된다.

이제 값을 읽어오는 일은 ref가 한다.

제어되는 컴포넌트와 제어되지 않는 컴포넌트

제어되는 컴포넌트

기존에 state를 통해 input을 관리했던 것을 제어되는 컴포넌트라고 부른다.

내부의 state가 리액트에 의해 제어되기 때문이다.

 

제어되지 않는 컴포넌트

방금처럼 react를 통하지 않고 직접적으로 DOM에 접근한 경우에는 제어되지 않는 컴포넌트라고 부른다.

 

왜 제어되지않는 컴포넌트라고 부르는 것일까?

이것들은 내부 state이기 때문이다. 이것들 안으로 반영되는 값들은 리액트에 의해 제어되지 않습니다.

 

 

'Lesson' 카테고리의 다른 글

React 완벽가이드 Session 10  (0) 2022.08.04

댓글