ReScript in Korean

엘리먼트와 JSX

원문

엘리먼트는 리액트 애플리케이션의 가장 작은 빌딩 블럭입니다. 이 페이지에서는 전용 JSX 문법을 사용해 React.element 를 어떻게 조작하는지 설명합니다.

참고 여기서는 여러분의 bsconfig.json 설정이 "reason": { "react-jsx": 3 }로 설정되어 있다고 가정합니다. 그렇지 않으면 JSX가 React 특정 형식으로 변환되지 않습니다.

기본 엘리먼트

첫 리액트 엘리먼트를 만들어보죠!

let element = <h1> {React.string("Hello World")} </h1>

element 바인딩과 {React.string("Hello World")} 표현식은 둘 다 리액트 애플리케이션 내에서 리액트 요소를 나타내는 기본 타입인 React.element 타입입니다. 엘리먼트는 애플리케이션을 DOM에 렌더링 할 때마다 화면에 표시되는 내용을 설명합니다.

children과 같은 다른 리액트 엘리먼트를 처리하는 함수를 만들고 싶다면 React.element 어노테이션을 작성해 사용하면 됩니다.

let wrapChildren = (children: React.element) => {
<div>
<h1> {React.string("Overview")} </h1>
children
</div>
}
wrapChildren(<div> {React.string("Let's use React with ReScript")} </div>)

React.element 타입은 ReactDOM.render(element, ...) 등 리액트 API 에서 많이 사용되기 때문에, 정의를 이해하는 것은 필수적입니다. JSX는 문자열React.element 로 자동으로 변환해주지 않습니다. (리스크립트는 이 타입 변환을 명시적으로 강제합니다). 예를 들어 <div> Hello World </div>의 경우는 타입 검사를 하지 않습니다. (which is actually a good thing because it's also a huge source for subtle bugs!), 여러분은 우선 "Hello World"React.string 함수를 사용해야합니다.

다행히 리스크립트의 리액트 바인딩은 관련 데이터 유형을 모두 React.element 변환하는 기능을 제공합니다.

JSX 와 엘리먼트 사용하기

JSX를 이용하는 복잡한 엘리먼트 합성을 할 수 있습니다.

let greeting = React.string("Hello ")
let name = React.string("Stranger");
/* element 의 type은 React.element 입니다 */
let element = <div className="myElement"> greeting name </div>

JSX는 리액트 애플리케이션의 엘리먼트 트리를 표현하는 주요한 방법입니다.

때때로, 기존 리액트 코드베이스와 상호 운용을 수행할 때 구문 제한으로 JSX 구문을 사용할 수 없는 상황에 놓이게 될 때도 있습니다. 이럴 때의 해결방법은 나중에 이스케이프 해치 챕터를 확인하세요.

엘리먼트 만들기

문자열, 정수, 실수, 배열로부터 엘리먼트 만들기

리액트 엘리먼트나 리액트 컴포넌트를 만들기 위해 JSX를 사용하는 것 외에도 React모듈은 기본 데이터 유형에서 엘리먼트를 생성하는 다양한 함수를 제공합니다.

React.string("Hello") /* "Hello"를 표시하는 새 엘리먼트 */
React.int(1) /* "1"을 표시하는 새 엘리먼트 */
React.float(1.0) /* "1.0"을 표시하는 새 엘리먼트 */

또한 여러 엘리먼트를 단일 요소로 표현하는 React.array 함수를 제공합니다. (리스트 데이터나 자식 엘리먼트를 통과시킬 때 유용합니다)

let element = React.array([
React.string("element 1"),
React.string("element 2"),
React.string("element 3")
])

참고 list는 런타임 오버 헤드를 포함하기 때문에 React.list 함수는 제공하지 않습니다. 리스크립트는 깔끔하고 관용적인 자바스크립트 출력에 더 관심있습니다. 엘리먼트 list를 단일 리액트 엘리먼트로 변경하려면 Belt.List.toArrayReact.array를 함께 사용하세요.

Null 엘리먼트 만들기

리스크립트는 강한 타입 특성에서 생기는 제약조건이 있기 때문에 element || null 같은 타입을 허락하지 않습니다. 값이 렌더링 되거나 렌더링 되지 않을 수 있는 조건을 표현할 때마다 Nothingness를 나타내는 React.null 상수가 필요합니다.

let name = Some("Andrea")
let element = switch name {
| Some(name) => <div> {React.string("Hello " ++ name)} </div>
| None => React.null
}
<div> element </div>

이스케이프 해치

참고 이 챕터에서는 JSX 자체에서 사용하는 저수준 API를 다룹니다. 저수준 API는 특정 JSX 구문 제한에 도달할 때 사용해야합니다. JSX 내부에 대한 자세한 정보는 JSX를 넘어서 섹션에서 찾을 수 있습니다.

컴포넌트 함수를 통한 엘리먼트 생성

참고 컴포넌트와 Props에 대한 상세한 부분은 컴포넌트와 Props 챕터에 설명되어있습니다.

때로는 React.element 생성을 더 잘 제어하기위해 구성 요소 함수를 전달하는것이 필요합니다. React.createElement 함수를 사용해 엘리먼트를 인스턴스화 하세요.

type props = {"name": string};
let render = (myComp: props => React.element) => {
<div>
{React.createElement(myComp, {"name": "Franz"})}
</div>
}

이 기능은 기존 리액트JS/자바스크립트와 상호작용할 때 종종 사용됩니다. 순수 리스크립트 리액트 애플리케이션은 렌더링 함수를 전달하는 것이 좋습니다("render prop" 이라고 불리기도 하죠).

let render = (renderMyComp: (~name: string) => React.element) => {
<div>
{renderMyComp("Franz")}
</div>
}

가변 Children 넘기기

세 번째 매개 변수로 자식 배열을 받는 React.createElementVariadic 함수가 있습니다.

type props = {"title": string, "children": React.element};
let render = (article: props => React.element) => {
let children = [React.string("Introduction"), React.string("Body")];
let props = {"title": "Article #1", "children": React.null};
{React.createElementVariadic(article, props, children)}
}

참고 여기서 우리는 타입 검사를 만족시키기 위해 "children": React.null을 prop으로 전달합니다. 리액트는 children props 을 무시하고 children array 를 더 선호합니다.

이 함수는 주로 JSX 변환에 이용됩니다. 그래서 일반적으로는 React.createElement를 사용하고 대신 children prop을 넘겨줍니다.

DOM 엘리먼트 만들기

DOM 엘리먼트(<div>, <span>, etc.)를 만들기 위해서는, ReactDOMRe.createDOMElementVariadic 함수를 사용합니다.

ReactDOMRe.createDOMElementVariadic("div", ~props=ReactDOM.domProps(~className="card", ()), []);

위 함수에는 ReactDOM.domProps 생성 함수가 필요합니다. 그렇기 때문에 리스크립트는 유효한 dom props만 전달하는지 확인할 수 있습니다. ReactDOM 모듈에서 사용가능한 모든 Props 목록을 찾을수 있습니다.

경고: The ReactDOMRe 모듈은 다음 rescript-react 메이저 릴리즈에서 제거될 예정이므로 사용에 주의하세요!

엘리먼트 복제

참고 이건 이스케이프 해치입니다. 기존 JS 코드/라이브러리의 상호운용에만 유용합니다.

새 인스턴스에 prop 값을 덮어 씌우거나 추가하기 위해 기존 엘리먼트를 복제해야하거나 data-name같은 유효하지 않은 prop 이름 설정이 필요한 경우가 있습니다. 이 때 React.cloneElement를 사용할 수 있습니다.

let original = <div className="hello"/>
/* className이 "world"로 설정 된 새 React.element 가 반환됩니다. */
React.cloneElement(original, {"className": "world", "data-name": "some name"});

위에서 언급한 기능은 리액트JS 코드베이스에서 일반적으로 사용되는 props spreading처럼 사용할 수도 있지만 안전하지 않은 특성과 부정확함으로 인해 props spreading 처럼 사용하는 것은 완전 비추합니다. (예: 정의되지 않은 props 컴포넌트에 추가하는 것은 넌센스이고 버그를 찾기 어렵게 만듭니다)

리스크립트에서는, 필요한 Props 를 컴포넌트에 명시적으로 전달하거나 renderProps을 사용합니다. 우리는 props를 보다 편리하게 전달하기 위해 JSX punning 구문을 도입했습니다.