리액트 - JSX 제한 사항 및 해결 방법

Hyeonseok Jeong·2022년 12월 18일
0

React

목록 보기
13/16

JSX 제한 사항 및 해결 방법

return(
	<h2>Hi there!</h2>
	<p>This does not work :-(</p>
)
  • 이 예처럼 루트 수준에서 JSX 요소들이 인접해 있으면 오류가 발생한다 다른 JSX 요소에 의해 래핑되지 않으면, 이 나란히 있는 JSX 요소를 반환하거나 변수에 저장하려고 한다. 이런식으로 하면 안된다.

왜냐하면 리액트에서는, 일반적으로 JSX에서는 루트 JSX 요소는 1개여야 한다

따라서 값을 반환하거나 값을 변수 또는 상수 또는 속성에 저장하려면 그값은 반드시 JSX 요소 1개여야 한다.

그런데 여기서 허용된 하나의 요소는 당연히 여러 자식들을 가질 수 있다.

이 이유는 유요한 자바스크립트가 아니기 때문이다.

자바스크립트에서는 둘 이상을 반환할 수 없는데, 두 개가 아니라 한 개의 숫자만 반환할 수 있다.

물론 배열을 반환할 수는 있고, 거기에 숫자 여러 개를 넣을 수 있다.

그럴수 있는 이유는 배열은 하나의 새로운 값이다. 즉, 배열 하나는 단지 객체 하나일 뿐이고 배열도 여전히 한 개만 반환하는 것이다. ( 객체 한개만 반환하는거고, 배열 두 개를 동시에 반환하는게 아니다)

return(
	React.createElement('h2', {}, 'Hi there!');
	React.createElement('p', {}, 'This does not work :-(');
)

JSX 코드는 리액트 createElement로 변환된다.

단 1개의 리액트 createElement 호출만 반환되어야 한다.

이제, 중첩되는 JSX요소들은 루트 요소 1개의 내부에서 여러 개가 나란히 있을 수 있다.

왜냐면 리액트 createElement 안에서 해당 루트 요소의 칠드런은 3, 4, 5 번째 인수가 될 수 있개 때문이다.

이를 해결 하기 위해서는 인접한 요소들을 div로 감싸면 된다.

return(
	<div>
		<h2>Hi there!</h2>
		<p>This does not work :-(</p>
	</div>
);

여기에서는 두 개의 중첩된 JSX요소를 반환한다.

div 하나에 넣어서 반환하는 것이다. 물론, 반드시 div일 필요는 없고 어떤 요소를 사용해도 된다.

사용자가 정의한 컴포넌트를 사용할 수도 있다.

중요한 것은, 반환하거나 상수에 저장하는 값은 하나여야 한다는 것이다.

div로 감싸게 되면 문제가 발생하는데 이를 div수프라고 한다.

<div>
	<div>
		<div>
			<div>
				<h2>Some content - yeah, this can really happen.</h2>
			</div>
		</div>
	</div>
</div>

div 수프 문제는 실제 DOM으로 렌더링될 때 리액트 컴포넌트가 많이 중첩될 수 있다.

그 모든 컴포넌트들은 여러 가지 이유로 div로 감쌀 필요가 있다.

또는 감싸는 컴포넌트가 필요하다.

이러한 불필요한 div들이 모두 실제 DOM으로 렌더링 된다.

그것들이 존재하는 이유는 JSX의 요구 사항 또는 제한 사항 때문일지라도 말이다.

더 큰 애플리케이션에서는 최종 사용자가 보는 최종 HTML 페이지에 불필요한 div 또는 기타 요소가 많이 있을 수 있다.

그것들이 거기 있는 이유는 감싸는 것이 필요하기 때문이다.

그것들은 페이지에 어떤 의미도 구조적인 의미도 갖지 않는데도 불구하고 말이다.

이처럼 많은 div또는 요소들이 감싸는 이유로 생성되게 되면 문제점은 css를 망칠수 있으며, 많은 div와 요소들은 렌더링시 무의미한 데이터를 만들어내므로 속도의 저하를 일으킬수 있다.

해결법으로는 Helpers 폴더를 만든후 Weapper.js 컴포넌트를 생성한다.

생성후 해당 컴포넌트에는 React를 import 하지 않는다 JSX 코드를 사용하지 않을것이기 때문이다.

대신

const Wrapper = props => {
	return props.children
} 

export default Wrapper;

와 같이 자바스크립트 문법을 사용하게 되면 해당 컴포넌트 는 빈 컴포넌트와 다름없다

props.children은 사용자 정의 컴포넌트에서 여는 태그와 닫는 태그 사이에 넣어준 모든 내용을 담고 있다.

여는 태그와 닫는 태그 사이에 있는 내용을 반환하는 컴포넌트는 유효하다.

만든 Wrapper 컴포넌트를 사용할 컴포넌트에 import 하고 div또는 요소 대신 사용하면 JSX 요구 사항을 충족시킬 수 있다.

다시 말하자면 해당 Wrapper 컴포넌트는 기본적으로 빈 컴포넌트 이다.

해당 컴포넌트가 하는일은 props.children을 반환하는 것 뿐이다.

당연히 해당 컴포넌트를 사용하여 하나의 요소로 사용하게 되면 DOM에 아무것도 렌더링 하지 않는다.

하지만 요구 사항은 DOM에 하나의 루트 컴포넌트를 렌더링 해야 한다는 것이었는데

요구사항은 단 하나의 루트 요소만 반환하거나 상수 또는 변수에 저장해야 한다는 거였다.

그 루트 요소를 Wrapper 라는 빈 컴포넌트가 역할을 해주는 것이다.

이와같은 빈 컴포넌트의 역할은 리액트에서도 지원해준다

바로 <React.Fragment></React.Fragment> 이다. 해당 프래그먼트를 사용하면 위와같이 빈 컴포넌트 를 만들어서 사용하는 것 과 같은 효과를 내며 이를 더 짧고 효율적으로 사용하면 <></> 와같이 사용 할 수있다.

물론 프로젝트마다 <></>를 사용할 수 있을수 도 있고 사용할 수 없을 수도 있다.
이는 빌드 워크 플로가 이를 지원해야 하기 때문이다.

  • JSX 문법 요소에서 배열 JSX문법 요소에서 배열로 작업을 하게되면 리액트는 모든 요소에 대한 키를 필요로 한다.
profile
풀스텍 개발자

0개의 댓글