mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-23 20:23:08 +00:00
Update Korean translation to 84af306
This commit is contained in:
@@ -19,6 +19,7 @@ UI를 가지고 할 수 있는 가장 기초적인 것은 데이터를 표시하
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -54,7 +55,6 @@ setInterval(function() {
|
||||
}, 500);
|
||||
```
|
||||
|
||||
|
||||
## 반응 적(Reactive) 업데이트
|
||||
|
||||
`hello-react.html` 파일을 웹 브라우저에서 열어 당신의 이름을 텍스트 필드에 써 보세요. React는 단지 시간을 표시하는 부분만을 바꿉니다 — 텍스트 필드 안에 입력한 것은 그대로 남아 있구요, 당신이 이 동작을 관리하는 그 어떤 코드도 쓰지 않았음에도 불구하고 말이죠. React는 그걸 올바른 방법으로 알아서 해줍니다.
|
||||
@@ -63,7 +63,6 @@ setInterval(function() {
|
||||
|
||||
이 컴포넌트에 대한 입력은 `props` 라고 불립니다 — "properties" 를 줄인 것이죠. 그들은 JSX 문법에서는 어트리뷰트로서 전달됩니다. 당신은 `props` 를 컴포넌트 안에서 불변의(immutable) 엘리먼트로서 생각해야 하고, `this.props` 를 덮어씌우려고 해서는 안됩니다.
|
||||
|
||||
|
||||
## 컴포넌트들은 함수와 같습니다
|
||||
|
||||
React 컴포넌트들은 매우 단순합니다. 당신은 그것들을 `props` 와 `state` (이것들은 나중에 언급할 것입니다) 를 받고 HTML을 렌더링하는 단순한 함수들로 생각해도 됩니다. 이걸 염두하면, 컴포넌트의 작동을 이해하는 것도 쉽습니다.
|
||||
@@ -72,7 +71,6 @@ React 컴포넌트들은 매우 단순합니다. 당신은 그것들을 `props`
|
||||
>
|
||||
> **한가지 제약이 있습니다**: React 컴포넌트들은 단 하나의 루트 노드(root node)만을 렌더할 수 있습니다. 만약 여러개의 노드들을 리턴하고 싶다면, 그것들은 단 하나의 루트 노드로 싸여져 있어야만 합니다.
|
||||
|
||||
|
||||
## JSX 문법
|
||||
|
||||
우리는 컴포넌트를 사용하는 것이 "템플릿"과 "디스플레이 로직(display logic)"을 이용하는 것보다 관심을 분리(separate concerns)하는 데에 올바른 방법이라고 강하게 믿고 있습니다. 우리는 마크업과 그것을 만들어내는 코드는 친밀하게 함께 결합되어있다고 생각합니다. 또한, 디스플레이 로직은 종종 매우 복잡하고, 그것을 템플릿 언어를 이용해 표현하는 것은 점점 사용하기 어렵게 됩니다.
|
||||
@@ -91,12 +89,11 @@ JSX를 이용하면:
|
||||
|
||||
우리는 이것이 React 앱들을 만들기 쉽게 하고, 디자이너들이 이 문법을 더 선호하는 것을 발견했습니다, 하지만 모든 사람은 그들만의 선호하는 워크플로우가 있기 마련이므로, **JSX는 React를 사용하기 위해 필수적이지는 않습니다.**
|
||||
|
||||
JSX는 매우 작은 언어입니다. 그것을 배우고 싶다면, [JSX 깊게 살펴보기](/react/docs/jsx-in-depth-ko-KR.html). 를 살펴 보시기 바랍니다. 또는, [우리의 온라인 JSX 컴파일러](/react/jsx-compiler.html)를 통해 문법이 변환되는 것을 살펴 보시기 바랍니다.
|
||||
JSX는 매우 작은 언어입니다. 그것을 배우고 싶다면, [JSX 깊게 살펴보기](/react/docs/jsx-in-depth-ko-KR.html)를 살펴 보시기 바랍니다. 또는, [바벨 REPL](https://babeljs.io/repl/)를 통해 문법이 변환되는 것을 살펴 보시기 바랍니다.
|
||||
|
||||
JSX는 HTML과 비슷하지만, 완전히 똑같지는 않습니다. [JSX의 실수하기 쉬운 부분들](/react/docs/jsx-gotchas-ko-KR.html)에 중요한 차이점들에 대해 설명되어 있습니다.
|
||||
|
||||
JSX를 사용하기 시작하기 위한 가장 쉬운 방법은 브라우저에서 작동하는 `JSXTransformer`를 사용하는 것입니다. 우리는 이것을 프로덕션에서는 사용하지 않기를 강하게 권장하는 바입니다. 당신은 우리의 커맨드 라인 [react-tools](https://www.npmjs.com/package/react-tools) 패키지를 이용하여 미리 컴파일(precompile)해 사용할 수 있습니다.
|
||||
|
||||
[바벨에서 JSX를 시작하는 여러 방법을 제공합니다](http://babeljs.io/docs/setup/). 여기에는 커맨드 라인 툴부터 루비 온 레일스 연동까지 다양한 방법이 있습니다. 가장 편한 툴을 사용하세요.
|
||||
|
||||
## JSX 없이 React 사용하기
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ var Nav = React.createClass({ });
|
||||
var Nav = React.createClass({displayName: "Nav", });
|
||||
```
|
||||
|
||||
[JSX 컴파일러](/react/jsx-compiler.html)를 보면 JSX에서 어떻게 네이티브 JavaScript로 변환(desugars)하는지 볼 수 있고, [HTML-JSX 변환기](/react/html-jsx.html)는 이미 있는 HTML을 JSX로 변환해 줍니다.
|
||||
[바벨 REPL](https://babeljs.io/repl/)를 보면 JSX에서 어떻게 네이티브 JavaScript로 변환(desugars)하는지 볼 수 있고, [HTML-JSX 변환기](/react/html-jsx.html)는 이미 있는 HTML을 JSX로 변환해 줍니다.
|
||||
|
||||
JSX를 사용 하시려면, [시작하기](/react/docs/getting-started-ko-KR.html) 가이드에서 어떻게 컴파일을 하기 위해 설정하는지 보실 수 있습니다.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ next: jsx-gotchas-ko-KR.html
|
||||
var component = <Component foo={x} bar={y} />;
|
||||
```
|
||||
|
||||
## Props의 변경은 나빠요.[^1]
|
||||
## Props의 변경은 나빠요
|
||||
|
||||
하지만 어떤 프로퍼티를 설정하고 싶은지 모른다면, 객체 레이어에 넣고 싶어질 수도 있습니다.
|
||||
|
||||
@@ -50,7 +50,3 @@ props는 변하지 않는 것으로 간주해야 합니다. props 객체를 변
|
||||
## 이상한 `...` 표기법은 무엇인가요?
|
||||
|
||||
`...` 연산자(스프레드 연산자)는 이미 [ES6의 배열](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator)에서 지원합니다. [객체 rest와 스프레드 프로퍼티](https://github.com/sebmarkbage/ecmascript-rest-spread)에 대한 ES7의 제안도 있습니다. JSX의 구문을 더 깔끔하게 하기 위해 지원되고 개발중인 표준을 활용하고 있습니다.
|
||||
|
||||
[^1]: 아무래도 좋지만, 이 제목의 원문 "Mutating Props is Bad, mkay"는 사우스 파크에
|
||||
나온 대사 "[Drug is bad, mkay](https://www.youtube-nocookie.com/watch?v=Uh7l8dx-h8M)"의
|
||||
패러디입니다.
|
||||
|
||||
@@ -8,7 +8,6 @@ next: multiple-components-ko-KR.html
|
||||
|
||||
이미 React에서 [어떻게 데이터를 표시](/react/docs/displaying-data-ko-KR.html)하는지를 배웠습니다. 이제 UI와의 상호작용을 어떻게 만드는지 살펴보죠.
|
||||
|
||||
|
||||
## 간단한 예제
|
||||
|
||||
```javascript
|
||||
@@ -35,34 +34,29 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 이벤트 핸들링과 통합적인(Synthetic) 이벤트
|
||||
|
||||
React에서의 이벤트 핸들러는 HTML에서 그러던 것처럼 간단히 카멜케이스 프로퍼티(camelCased prop)로 넘기면 됩니다. React의 모든 이벤트는 통합적인 이벤트 시스템의 구현으로 IE8 이상에서는 같은 행동이 보장됩니다. 즉, React는 사양에 따라 어떻게 이벤트를 일으키고(bubble) 잡는지 알고 있고, 당신이 사용하는 브라우저와 관계없이 이벤트 핸들러에 전달되는 이벤트는 [W3C 사양](http://www.w3.org/TR/DOM-Level-3-Events/)과 같도록 보장됩니다.
|
||||
|
||||
|
||||
## 기본 구현: 오토바인딩과 이벤트 델리게이션
|
||||
<a name="under-the-hood-autobinding-and-event-delegation"></a>
|
||||
|
||||
코드를 고성능으로 유지하고 이해하기 쉽게 하기 위해, React는 보이지 않는 곳에서 몇 가지 일을 수행합니다.
|
||||
|
||||
**오토바인딩:** JavaScript에서 콜백을 만들 때, 보통은 `this`의 값이 정확하도록 명시적으로 메소드를 인스턴스에 바인드해야 합니다. React에서는 모든 메소드가 자동으로 React의 컴포넌트 인스턴스에 바인드됩니다. React가 바인드 메소드를 캐시하기 때문에 매우 CPU와 메모리에 효율적입니다. 타이핑해야 할 것도 줄어들죠!
|
||||
**오토바인딩:** JavaScript에서 콜백을 만들 때, 보통은 `this`의 값이 정확하도록 명시적으로 메소드를 인스턴스에 바인드해야 합니다. React에서는 모든 메소드가 자동으로 React의 컴포넌트 인스턴스에 바인드됩니다.(ES6 클래스 문법을 사용할 때는 재외하고) React가 바인드 메소드를 캐시하기 때문에 매우 CPU와 메모리에 효율적입니다. 타이핑해야 할 것도 줄어들죠!
|
||||
|
||||
**이벤트 델리게이션:** React는 실제로는 노드자신에게 이벤트 핸들러를 붙이지 않습니다. React가 시작되면 React는 탑 레벨의 단일 이벤트 리스너로 모든 이벤트를 리스닝하기 시작합니다. 컴포넌트가 마운트되거나 언마운트 될 때, 이벤트 핸들러는 그냥 내부 매핑에서 넣거나 뺄 뿐입니다. 이벤트가 발생하면, React는 이 매핑을 사용해서 어떻게 디스패치할 지를 알게 됩니다. 매핑에 이벤트 핸들러가 남아있지 않으면, React의 이벤트 핸들러는 그냥 아무것도 하지 않습니다. 왜 이 방식이 빠른지 더 알고 싶으시면, [David Walsh의 멋진 블로그 글](http://davidwalsh.name/event-delegate)을 읽어 보세요.
|
||||
|
||||
|
||||
## 컴포넌트는 그냥 state 머신일 뿐
|
||||
|
||||
React는 UI를 간단한 state 머신이라 생각합니다. UI를 다양한 state와 그 state의 렌더링으로 생각함으로써 UI를 일관성 있게 관리하기 쉬워집니다.
|
||||
|
||||
React에서는, 간단히 컴포넌트의 state를 업데이트하고, 이 새로운 state의 UI를 렌더링합니다. React는 DOM의 변경을 가장 효율적인 방법으로 관리해줍니다.
|
||||
|
||||
|
||||
## state의 동작 원리
|
||||
|
||||
React에게 데이터의 변경을 알리는 일반적인 방법은 `setState(data, callback)`을 호출하는 것입니다. 이 메소드는 `this.state`에 `data`를 머지하고 컴포넌트를 다시 렌더링 합니다. 컴포넌트의 재-렌더링이 끝나면, 생략가능한 `callback`이 호출됩니다. 대부분의 경우 React가 UI를 최신상태로 유지해주기 때문에 `callback`을 사용할 필요가 없습니다.
|
||||
|
||||
|
||||
## 어떤 컴포넌트가 state를 가져야 할까요?
|
||||
|
||||
대부분의 컴포넌트는 `props`로부터 데이터를 받아 렌더할 뿐입니다만, 가끔 유저 인풋, 서버 요청, 시간의 경과에 반응해야 할 필요가 있습니다. 이럴 때 state를 사용합니다.
|
||||
@@ -71,7 +65,6 @@ React에게 데이터의 변경을 알리는 일반적인 방법은 `setState(da
|
||||
|
||||
일반적인 패턴은 데이터만 렌더하는 여러 상태를 가지지 않은 컴포넌트를 만들고, 그 위에 상태기반(stateful) 컴포넌트를 만들어 계층 안의 자식 컴포넌트에게 `props`를 통해 state를 전달하는 것입니다. state를 가지지 않은 컴포넌트가 선언적인 방법으로 데이터를 렌더링 하는 동안, 상태기반 컴포넌트는 모든 상호작용 로직을 캡슐화합니다.
|
||||
|
||||
|
||||
## state를 어떻게 *써야* 할까요?
|
||||
|
||||
**state는 컴포넌트의 이벤트 핸들러에 의해 UI 업데이트를 트리거할때 변경될 가능성이 있어, 그때 사용할 데이터를 가져야 합니다.** 실제 앱에서는 이 데이터는 매우 작고 JSON 직렬화 가능한 경향이 있습니다. 상태기반 컴포넌트를 만들때, 가능한 작게 state를 서술하고 `this.state`에만 저장하도록 해보세요. 그냥 `render()` 안에서 이 state를 기반으로 다른 모든 정보를 계산합니다. 이 방식으로 애플리케이션을 작성하고 생각하면 가장 최적의 애플리케이션으로 발전해가는 경향이 있다는 것을 발견하게 될 것입니다. 꼭 필요하지 않은 값이나 계산된 값을 state에 추가하는 것은 render가 그것을 계산하는 대신에 명시적으로 그것들을 맞춰줘야 하는 것을 의미하기 때문이죠.
|
||||
@@ -82,4 +75,4 @@ React에게 데이터의 변경을 알리는 일반적인 방법은 `setState(da
|
||||
|
||||
* **계산된 데이터:** state에 따라 값을 미리 계산하는 것에 대해 염려하지 마세요. 계산은 모두 `render()`에서 하는 것이 UI의 일관성을 유지하기 쉽습니다. 예를 들어, state에서 list items 배열을 가지고 있고 문자열으로 카운트를 렌더링 할 경우, state에 저장하기보다는 그냥 `render()` 메소드안에서 `this.state.listItems.length + ' list items'`를 렌더하세요.
|
||||
* **React 컴포넌트:** 가지고 있는 props와 state로 `render()`안에서 만드세요.
|
||||
* **props에서 복사한 데이터:** 가능한 한 원래의 소스로 props를 사용하도록 해보세요. props를 state에 저장하는 단 하나의 올바른 사용법은 이전 값을 알고 싶을 때입니다. props는 시간이 지나면 변경될 수도 있기 때문이죠.
|
||||
* **props에서 복사한 데이터:** 가능한 한 원래의 소스로 props를 사용하도록 해보세요. props를 state에 저장하는 단 하나의 올바른 사용법은 이전 값을 알고 싶을 때입니다. props는 부모 컴포넌트의 재 렌더링의 결과 변경될 수도 있기 때문이죠.
|
||||
|
||||
@@ -8,12 +8,10 @@ next: reusable-components-ko-KR.html
|
||||
|
||||
지금까지, 단일 컴포넌트에서 데이터를 표시하고 유저 입력을 다루는 것을 살펴보았습니다. 다음엔 React의 최고의 기능 중 하나인 조합가능성(composability)을 살펴봅시다.
|
||||
|
||||
|
||||
## 동기: 관심의 분리
|
||||
|
||||
명확히 정의된 인터페이스와 다른 컴포넌트를 재사용해 모듈러 컴포넌트를 구축하면, 함수와 클래스를 이용했을 때 얻을 수 있는 이점 대부분을 얻을 수 있습니다. 특히 앱에서 *다른 관심을 분리*할 수 있습니다.아무리 간단히 새 컴포넌트를 만들었다고 해도 말이죠. 당신의 애플리케이션에서 쓸 커스텀 컴포넌트 라이브러리를 만들어서, 당신의 도메인에 최적화된 방법으로 UI를 표현할 수 있게 됩니다.
|
||||
|
||||
|
||||
## 조합(Composition) 예제
|
||||
|
||||
간단히 페이스북 그래프 API를 사용해 프로필 사진과 유저이름을 보여주는 아바타 컴포넌트를 만든다고 합시다.
|
||||
@@ -54,14 +52,12 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 소유권(Ownership)
|
||||
|
||||
위의 예제에서, `Avatar` 인스턴스는 `ProfilePic`과 `ProfileLink`인스턴스를 *가지고* 있습니다. React에서 **소유자는 다른 컴포넌트의 `props`를 설정하는 컴포넌트입니다**. 더 정식으로 말하면, `X` 컴포넌트가 `Y` 컴포넌트의 `render()` 메소드 안에서 만들어졌다면, `Y`가 `X`를 *소유하고* 있다고 합니다. 앞에서 설명한 바와 같이, 컴포넌트는 자신의 `props`를 변경할 수 없습니다. `props`는 언제나 소유자가 설정한 것과 일치합니다. 이와 같은 중요한 성질은 UI가 일관성 있도록 해줍니다.
|
||||
위의 예제에서, `Avatar` 인스턴스는 `ProfilePic`과 `ProfileLink`인스턴스를 *가지고* 있습니다. React에서 **소유자는 다른 컴포넌트의 `props`를 설정하는 컴포넌트입니다**. 더 정식으로 말하면, `X` 컴포넌트가 `Y` 컴포넌트의 `render()` 메소드 안에서 만들어졌다면, `Y`가 `X`를 *소유하고* 있다고 합니다. 앞에서 설명한 바와 같이, 컴포넌트는 자신의 `props`를 변경할 수 없습니다. `props`는 언제나 소유자가 설정한 것과 일치합니다. 이와 같은 근본적인 불변성은 UI가 일관성 있도록 해줍니다.
|
||||
|
||||
소유(owner-ownee)관계와 부모·자식 관계를 구별하는 것은 중요합니다. 부모·자식 관계가 DOM에서부터 쓰던 익숙하고 이미 알고있던 단순한 것인 한편, 소유관계는 React 고유의 것입니다. 위의 예제에서, `Avatar`는 `div`, `ProfilePic`, `ProfileLink`인스턴스를 소유하고, `div`는 `ProfilePic`과 `ProfileLink`인스턴스의 (소유자가 아닌) **부모**입니다.
|
||||
|
||||
|
||||
## 자식
|
||||
|
||||
React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트나 JavaScript 표현식을 시작과 끝 태그 사이에 넣을 수 있습니다. 이렇게 말이죠.
|
||||
@@ -72,7 +68,6 @@ React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트
|
||||
|
||||
`Parent`는 `this.props.children`라는 특수 prop으로 자식들을 읽을 수 있습니다. **`this.props.children` 는 불투명한 데이터 구조이며,** [React.Children 유틸리티](/react/docs/top-level-api-ko-KR.html#react.children)를 사용해 자식들을 관리합니다.
|
||||
|
||||
|
||||
### 자식 Reconciliation (비교조정)
|
||||
|
||||
**Reconciliation은 React가 DOM을 각각 새로운 렌더 패스에 업데이트하는 과정입니다.** 일반적으로, 자식은 렌더하는 순서에 따라 비교조정됩니다. 예를 들어, 각각의 마크업을 생성하는 두 개의 렌더 패스가 있다고 해봅시다.
|
||||
@@ -91,7 +86,6 @@ React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트
|
||||
|
||||
직관적으로 보면, `<p>Paragraph 1</p>`가 없어졌습니다만 그러는 대신에, React는 첫 번째 자식의 텍스트를 비교조정하고 마지막 자식을 파괴하도록 DOM을 비교조정할 것입니다. React는 자식들의 *순서*에 따라 비교조정합니다.
|
||||
|
||||
|
||||
### 상태기반(Stateful) 자식
|
||||
|
||||
대부분의 컴포넌트에서는, 이것은 큰 문제가 아닙니다. 하지만 렌더 패스 간에 `this.state`를 유지하는 상태기반의 컴포넌트에서는 매우 문제가 될 수 있습니다.
|
||||
@@ -111,7 +105,6 @@ React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트
|
||||
</Card>
|
||||
```
|
||||
|
||||
|
||||
<a name="dynamic-children"></a>
|
||||
### 동적 자식
|
||||
|
||||
@@ -179,7 +172,6 @@ ReactFragment 객체를 넘기는 것으로 자식에 키를 할당할 수도
|
||||
|
||||
React에서 데이터는 위에서 말한 것처럼 `props`를 통해 소유자로부터 소유한 컴포넌트로 흐릅니다. 이것은 사실상 단방향 데이터 바인딩입니다. 소유자는 `props`나 `state`를 기준으로 계산한 어떤 값으로 소유한 컴포넌트의 props를 바인드합니다. 이 과정은 재귀적으로 발생하므로, 데이터의 변경은 자동으로 모든 곳에 반영됩니다.
|
||||
|
||||
|
||||
## 성능의 주의점
|
||||
|
||||
소유자가 가지고 있는 노드의 수가 많아지면 데이터가 변화하는 비용이 증가할 것으로 생각할 수도 있습니다. 좋은 소식은 JavaScript의 속도는 빠르고 `render()` 메소드는 꽤 간단한 경향이 있어, 대부분 애플리케이션에서 매우 빠르다는 점입니다. 덧붙여, 대부분의 병목 현상은 JS 실행이 아닌 DOM 변경에서 일어나고, React는 배치와 탐지 변경을 이용해 최적화해 줍니다.
|
||||
|
||||
@@ -8,7 +8,6 @@ next: transferring-props-ko-KR.html
|
||||
|
||||
인터페이스를 설계할 때, 공통적으로 사용되는 디자인 요소들(버튼, 폼 필드, 레이아웃 컴포넌트 등.)을 잘 정의된 인터페이스의 재사용 가능한 컴포넌트로 분해합니다. 이런 방법으로 다음에 UI를 구축할 때에는 훨씬 적은 코드로 만들 수 있습니다. 이 말은 더 빠른 개발 시간, 더 적은 버그, 더 적은 용량으로 할 수 있다는 뜻이죠.
|
||||
|
||||
|
||||
## Prop 검증
|
||||
|
||||
앱의 규모가 커지면 컴포넌트들이 바르게 사용되었는지 확인하는게 도움이 됩니다. 확인은 `propTypes`를 명시해서 할 수 있습니다. `React.PropTypes`는 받은 데이터가 적절한지(valid) 확인하는데 사용할 수 있는 다양한 검증자(validator)를 제공합니다. prop에 부적절한 값을 명시한다면 JavaScript 콘솔에 경고가 보일 것입니다. 성능상의 문제로 `propTypes`는 개발 모드에서만 검사됩니다. 다음은 제공되는 검증자를 설명하는 예제입니다.
|
||||
@@ -78,7 +77,6 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## 기본 Prop 값
|
||||
|
||||
React는 매우 선언적(declarative)인 방법으로 `props`의 기본값을 정의할 수 있게 해줍니다.
|
||||
@@ -230,3 +228,30 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
### 믹스인 안됨
|
||||
|
||||
불행하게도 ES6는 믹스인에 대한 지원이 없이 출시되었기 때문에, React에서 ES6 클래스를 사용한다면 믹스인을 사용할 방법이 없습니다. 대신, 우리는 믹스인에 의존하지 않고도 동작하도록 만들기 위해 열심히 노력하고 있습니다.
|
||||
|
||||
<a name="stateless-functions"></a>
|
||||
## 상태를 가지지 않는 함수
|
||||
|
||||
React 클래스를 일반 JavaScript 함수로 작성할 수도 있습니다. 상태를 가지지 않는 함수 문법을 사용하는 예제입니다.
|
||||
|
||||
```javascript
|
||||
function HelloMessage(props) {
|
||||
return <div>Hello {props.name}</div>;
|
||||
}
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
아니면 ES6의 화살표 문법을 사용할 수 있습니다.
|
||||
|
||||
```javascript
|
||||
var HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
이 단순화된 컴포넌트 API는 prop의 순수 함수인 컴포넌트를 나타냅니다. 이 컴포넌트는 내부 상태가 없어야 하고, 내부 인스턴스가 없어야 하고, 컴포넌트 생명주기 메소드가 없어야 합니다. 아무런 준비 과정없이 입력에 대한 순수한 기능적 변환이어야 합니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 상태를 가지지 않는 함수는 내부 인스턴스가 없기 때문에, ref를 상태를 가지지않는 함수에 넣을 수 없습니다. 상태를 가지지 않는 함수는 명령형(imperative) API를 제공하지 않기 때문에 일반적으로 이것은 문제가 되지 않습니다. 명령형 API없이 인스턴스에 할 수 있는 것이 많지 않기도 하죠. 하지만 상태를 가지지 않는 컴포넌트의 DOM 노드를 검색하길 원한다면, 반드시 상태 기반 컴포넌트(예. ES6 클래스 컴포넌트)로 컴포넌트를 감싸고 상태 기반 래퍼 컴포넌트에 ref를 붙여야 합니다.
|
||||
|
||||
이상적으로는, 대부분의 컴포넌트는 상태를 가지지 않는 함수여야 합니다. 왜냐 하면 이런 상태를 가지지 않는 컴포넌트는 React 코어 안에서 더 빠른 코드 경로를 거치기 때문입니다. 이는 가능한 한 추천하는 패턴입니다.
|
||||
|
||||
@@ -51,7 +51,8 @@ ReactDOM.render(
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 아래의 예제에서는 실험적인 ES7 문법이 사용되었기 때문에 `--harmony ` 플래그가 필요합니다. 브라우저에서 JSX 변환기를 사용 중이라면, `<script type="text/jsx;harmony=true">`를 사용해 스크립트를 작성하세요. 자세히 알아보려면 아래의 [잔여 프로퍼티와 스프레드 프로퍼티 ...](/react/docs/transferring-props-ko-KR.html#rest-and-spread-properties-...)를 확인하세요.
|
||||
> `...` 구문은 객체 잔여 스프레드 제안의 일부입니다. 이 제안은 표준화 과정에 있습니다. 더 자세한 내용은 밑의 [잔여 프로퍼티와 스프레드 프로퍼티 ...](/react/docs/transferring-props.html#rest-and-spread-properties-...) 부분을 참고하세요.
|
||||
|
||||
|
||||
때로는 모든 프로퍼티를 일일이 전달 하는것은 지루하고 덧없는 작업입니다. 이 경우 [구조 해체 할당(destructuring assignment)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)을 다른 프로퍼티를 함께 사용해 미상의 프로퍼티를 추출할 수 있습니다.
|
||||
|
||||
@@ -133,7 +134,7 @@ var FancyCheckbox = React.createClass({
|
||||
|
||||
잔여(Rest, `...`) 프로퍼티는 객체에서 소비되지 않은 나머지 프로퍼티를 추출해 새로운 객체로 만들 수 있게 해 줍니다. 구조 해체 패턴에서 열거된 다른 프로퍼티들은 모두 제외됩니다.
|
||||
|
||||
이는 [ES7 제안](https://github.com/sebmarkbage/ecmascript-rest-spread)의 실험적인 구현체입니다.
|
||||
이 제안은 2 단계에 돌입해 이제 바벨에서 기본값으로 활성화되어있습니다. 바벨의 이전 버전은 `babel --optional es7.objectRestSpread`로 명시적으로 활성화 할 필요가 있을 수도 있습니다.
|
||||
|
||||
```javascript
|
||||
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
|
||||
|
||||
@@ -68,6 +68,9 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
|
||||
이것은 사용자 입력을 받아들이지만, 시작에서부터 140자로 값을 자릅니다.
|
||||
|
||||
### 체크박스와 라디오 버튼의 잠제적인 문제
|
||||
|
||||
변경 핸들링을 일반화하기 위해 React는 `change` 이벤트 대신에 `click` 이벤트를 사용하는 것에 주의하세요. `change` 핸들러 안에서 `preventDefault`를 호출하는 경우를 재외하고 이 동작은 예상대로 동작합니다. 이런 경우 `preventDefault`를 제거하거나, `setTimeout`에 `checked`의 전환을 넣어서 해결 가능합니다.
|
||||
|
||||
## 제어되지 않는(Uncontrolled) 컴포넌트
|
||||
|
||||
@@ -91,7 +94,7 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
}
|
||||
```
|
||||
|
||||
이 예제는 위에있는 **제어되는 컴포넌트**에 더 가깝게 동작할 것입니다.
|
||||
이 예제는 위에있는 **제어되지 않는 컴포넌트**에 더 가깝게 동작할 것입니다.
|
||||
|
||||
마찬가지로, `<input>`은 `defaultChecked`를 지원하고 `<select>`는 `defaultValue`를 지원합니다.
|
||||
|
||||
@@ -99,10 +102,8 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
>
|
||||
> `defaultValue`, `defaultChecked` prop은 최초 렌더에서만 사용됩니다. 뒤에 일어나는 렌더에서 값을 업데이트할 필요가 있다면, [제어되는(controlled) 컴포넌트](#controlled-components)를 사용하셔야 합니다.
|
||||
|
||||
|
||||
## 심화 주제
|
||||
|
||||
|
||||
### 왜 제어되는 컴포넌트인가요?
|
||||
|
||||
React에서 `<input>`같은 폼 컴포넌트를 사용하면, 전통적인 폼 HTML을 쓸 때에는 없던 어려운 문제가 있습니다. 예를 들어 HTML에서
|
||||
@@ -123,7 +124,6 @@ HTML과 다르게, React 컴포넌트는 초기화 시점 뿐만 아니라, 어
|
||||
|
||||
이 메소드가 어떤 시점에도 뷰를 기술하기 때문에, 텍스트 input의 값은 *언제나* `Untitled`입니다.
|
||||
|
||||
|
||||
### 왜 Textarea에 value를 사용하나요?
|
||||
|
||||
HTML에서, `<textarea>`의 값은 보통 그것의 자식들로 설정됩니다.
|
||||
@@ -141,7 +141,6 @@ HTML에서는 이렇게 하면 여러 줄의 값을 쉽게 개발자가 넣을
|
||||
|
||||
자식들을 사용하기로 *했다면*, 자식들은 `defaultValue`처럼 동작할 것입니다.
|
||||
|
||||
|
||||
### 왜 Select에 value를 사용하나요?
|
||||
|
||||
HTML `<select>`에서 선택된 `<option>`은 보통 option의 `selected` 어트리뷰트로 기술됩니다. React에서는 컴포넌트를 관리하기 쉽게 하기 위해, 다음 형식이 대신 채용됐습니다.
|
||||
|
||||
@@ -11,7 +11,7 @@ React는 대부분의 경우 직접 DOM을 다루지 않아도 될만큼 강력
|
||||
|
||||
## 가상의 DOM
|
||||
|
||||
React는 DOM을 직접 다루지 않기 때문에 굉장히 빠릅니다. React는 메모리에(in-memory) DOM의 표상(representation)을 관리합니다. `render()` 메소드는 DOM의 *서술*를 반환하고, React는 이를 메모리에 있는 DOM의 표상과 비교(diff)해 가장 빠른 방식으로 계산해서 브라우저를 업데이트해 줍니다.
|
||||
React는 DOM을 직접 다루지 않기 때문에 매우 빠릅니다. React는 메모리에(in-memory) DOM의 표상(representation)을 관리합니다. `render()` 메소드는 사실은 DOM의 *서술*를 반환하고, React는 이를 메모리에 있는 DOM의 표상과 비교해 가장 빠른 방식으로 계산해서 브라우저를 업데이트해 줍니다.
|
||||
|
||||
게다가 React는 브라우저의 괴악함(quirks)에도 불구하고 모든 이벤트 객체가 W3C 명세를 보장하도록 통합적인 이벤트 시스템을 구현했습니다. 모든 것이 일관된 방식으로 일어나고(bubbles) 효율적으로 크로스 브라우징을 수행합니다. 심지어 IE8에서도 HTML5 이벤트를 사용할 수 있습니다!
|
||||
|
||||
@@ -20,45 +20,7 @@ React는 DOM을 직접 다루지 않기 때문에 굉장히 빠릅니다. React
|
||||
|
||||
## Refs와 findDOMNode()
|
||||
|
||||
브라우저와 상호 작용하려면 DOM 노드에 대한 참조가 필요합니다. React는 `ReactDOM.findDOMNode(component)` 함수를 갖고 있으며, 이를 통해서 컴포넌트의 DOM 노드의 참조를 얻을 수 있습니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> `findDOMNode()`는 마운트 된 컴포넌트에서만 동작합니다 (DOM에 배치된 컴포넌트를 말합니다). 아직 마운트 되지 않은 컴포넌트에서 이를 호출하려고 하면 (컴포넌트가 아직 생성되기 이전인 `render()` 시점에 `findDOMNode()`를 호출한다든가) 예외가 발생합니다.
|
||||
|
||||
React 컴포넌트에 대한 참조는 현재의 React 컴포넌트를 위해 `this`를, 소유한 컴포넌트의 참조를 얻기 위해 refs를 사용해 얻을 수 있습니다. 다음과 같이 동작합니다:
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// raw DOM API를 사용해 명시적으로 텍스트 인풋을 포커스 합니다.
|
||||
ReactDOM.findDOMNode(this.refs.myTextInput).focus();
|
||||
},
|
||||
render: function() {
|
||||
// ref 어트리뷰트는 컴포넌트가 마운트되면 그에 대한 참조를 this.refs에 추가합니다.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref="myTextInput" />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Refs 심화
|
||||
|
||||
[refs 심화](/react/docs/more-about-refs-ko-KR.html) 문서에서 refs를 효율적으로 사용하는 법을 포함해 더 많은 내용을 익혀보세요.
|
||||
브라우저와 상호 작용하려면 DOM 노드에 대한 참조가 필요합니다. `ref`를 어떤 엘리먼트에도 붙일 수 있으며, 이를 통해 컴포넌트 **지원 인스턴스**를 참조 할 수 있습니다. 이는 컴포넌트에 필수 적인 기능을 호출할 때나 기저의 DOM 노드에 접근하고 싶을 때 유용합니다. [refs에서 컴포넌트로](/react/docs/more-about-refs-ko-KR.html) 문서에서 refs를 효율적으로 사용하는 법을 포함해 더 많은 내용을 익혀보세요.
|
||||
|
||||
|
||||
<a name="component-lifecycle"></a>
|
||||
@@ -72,14 +34,12 @@ ReactDOM.render(
|
||||
|
||||
React는 이 프로세스에 훅을 지정할 수 있는 생명주기 메소드를 제공합니다. 발생 직전 시점을 위한 **will** 메소드, 발생 직후 시점을 위한 **did** 메소드가 있습니다.
|
||||
|
||||
|
||||
### Mounting
|
||||
|
||||
* `getInitialState(): object`는 컴포넌트가 마운트되기 전에 호출됩니다. 상태기반 컴포넌트는 이를 구현하고 초기 상태 데이터를 리턴합니다.
|
||||
* `componentWillMount()`는 마운팅되기 직전에 호출됩니다.
|
||||
* `componentDidMount()`는 마운팅 직후 호출됩니다. 초기화에 필요한 DOM 노드는 이곳에 있어야 합니다.
|
||||
|
||||
|
||||
### Updating
|
||||
|
||||
* `componentWillReceiveProps(object nextProps)`는 마운트된 컴포넌트가 새로운 props을 받을 때 호출됩니다. 이 메소드는 `this.props`와 `nextProps`을 비교하여 `this.setState()`를 사용해 상태 변환을 수행하는데 사용되야 합니다.
|
||||
@@ -87,19 +47,15 @@ React는 이 프로세스에 훅을 지정할 수 있는 생명주기 메소드
|
||||
* `componentWillUpdate(object nextProps, object nextState)`는 업데이트가 발생하기 직전에 호출됩니다. 이 시점에는 `this.setState()`를 호출할 수 없습니다.
|
||||
* `componentDidUpdate(object prevProps, object prevState)`는 업데이트가 발생한 후 즉시 호출됩니다.
|
||||
|
||||
|
||||
### Unmounting
|
||||
|
||||
* `componentWillUnmount()`는 컴포넌트가 언마운트되어 파괴되기 직전에 호출됩니다. 정리(Cleanup)는 여기서 처리해야 합니다.
|
||||
|
||||
|
||||
### Mounted 메소드
|
||||
|
||||
_마운트된_ 합성 컴포넌트들은 다음과 같은 메소드를 지원합니다:
|
||||
|
||||
* `findDOMNode(): DOMElement`는 렌더링 된 DOM 노드에 대한 참조를 얻기 위해 모든 마운트된 컴포넌트에서 호출할 수 있습니다.
|
||||
* `forceUpdate()`는 `this.setState`를 사용하지 않고 컴포넌트 state의 더 깊은 측면(deeper aspect)의 변경된 것을 알고 있을 때 모든 마운트된 컴포넌트에서 호출할 수 있습니다.
|
||||
|
||||
* `component.forceUpdate()`는 `this.setState()`를 사용하지 않고 변경된 컴포넌트의 상태의 변경을 적용하고 싶을 때 마운트된 컴포넌트에서 사용할 수 있습니다.
|
||||
|
||||
## 브라우저 지원과 Polyfill
|
||||
|
||||
@@ -107,7 +63,6 @@ _마운트된_ 합성 컴포넌트들은 다음과 같은 메소드를 지원합
|
||||
|
||||
그 철학에 더하여, 우리는 또한 JS 라이브러리의 저자로서 polyfill을 라이브러리에 포함해서 배포하지 않습니다. 만약 모든 라이브러리가 이런 짓을 하면, 같은 polyfill을 여러 번 내리게 되어 쓸모없이 크기만 차지하는 죽은 코드들을 만들 것 입니다. 당신의 제품이 구식 브라우저를 지원해야한다면, [es5-shim](https://github.com/es-shims/es5-shim) 같은 녀석을 사용할 기회가 있었을 겁니다.
|
||||
|
||||
|
||||
### Polyfill은 구식 브라우저를 지원하기 위해 필요하다
|
||||
|
||||
[kriskowal's es5-shim](https://github.com/es-shims/es5-shim)의 `es5-shim.js`는 React에 필요한 다음의 기능을 제공합니다:
|
||||
@@ -134,12 +89,10 @@ _마운트된_ 합성 컴포넌트들은 다음과 같은 메소드를 지원합
|
||||
|
||||
`<section>`, `<article>`, `<nav>`, `<header>`, `<footer>`등 HTML5 엘리먼트를 IE8에서 이용하려면 [html5shiv](https://github.com/aFarkas/html5shiv)같은 스크립트가 추가로 필요합니다.
|
||||
|
||||
|
||||
### 크로스 브라우징 이슈
|
||||
|
||||
React가 브라우저별 차이점을 썩 잘 추상화하긴 했지만 일부는 한정적이거나 우리가 발견하지 못한 이상한(quirky) 동작을 보여주기도 합니다.
|
||||
|
||||
|
||||
#### IE8에서의 onScroll 이벤트
|
||||
|
||||
IE8에서는 `onScroll` 이벤트가 일어나지(bubble) 않으며, IE8은 이벤트의 캡쳐링 단계를 위한 핸들러를 정의하는 API를 갖고 있지 않습니다. 이는 React가 이 이벤트를 이해(listen) 할 방법이 없음을 뜻합니다. 현재 이 이벤트 핸들러는 IE8에서 무시됩니다.
|
||||
|
||||
@@ -1,137 +1,125 @@
|
||||
---
|
||||
id: more-about-refs-ko-KR
|
||||
title: refs 심화
|
||||
title: refs에서 컴포넌트로
|
||||
permalink: more-about-refs-ko-KR.html
|
||||
prev: working-with-the-browser-ko-KR.html
|
||||
next: tooling-integration-ko-KR.html
|
||||
---
|
||||
render 메소드를 통해 UI 구조를 얻은 다음, 반환된 컴포넌트 인스턴스에 접근하거나 메소드를 호출할 방법이 필요할 수도 있습니다. 반응적 데이터 플로우가 `render()`의 결과물에서 최신의 `props`가 각각의 자식으로 보내진 것을 항상 보장하기 때문에 애플리케이션의 데이터 플로우를 만드는데 대체로 이런 작업은 필요가 없지만, 여전히 이런 작업이 필요하거나 유리한 경우가 있긴 합니다.
|
||||
컴포넌트를 빌드한 후에는 `render()`에서 반환된 컴포넌트 인스턴스에 접근하거나 메소드를 호출할 방법이 필요할 수도 있습니다. 반응적 데이터 플로우가 `render()`의 결과물에서 최신의 `props`가 각각의 자식으로 보내진 것을 항상 보장하기 때문에 애플리케이션의 데이터 플로우를 만드는데 대체로 이런 작업은 필요가 없지만, 여전히 이런 작업이 필요하거나 유리한 경우가 있긴 합니다. React는 이를 위해 `refs`라는 탈출구를 제공합니다. `refs`(레퍼런스)는 특히 다음과 같은 경우 유용합니다: 컴포넌트에 의해 렌더된 DOM 마크업을 찾을때 (인스턴스내의 절대적인 위치), 큰 프로젝트의 일부에 React 컴포넌트를 사용하는 경우 또는 기존의 코드베이스를 React로 변경하는 경우.
|
||||
|
||||
ref를 어떻게 얻는지 살펴보고, 예제를 완성해 봅시다.
|
||||
|
||||
인스턴스의 하위 계층구조에 존재하는 `<input />` 엘리먼트의 value를 빈 문자열(`''`)로 업데이트한 후 포커스 하는 경우를 생각해 봅시다.
|
||||
## ReactDOM.render에서 반환된 ref
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
this.setState({userInput: ''}); // 입력내용을 지워줍니다
|
||||
// 이제 <input />에 포커스를 주길 원합니다!
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
클릭해서 초기화하고 포커스주기
|
||||
</div>
|
||||
<input
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
컴포넌트에서 정의한, 가상의 DOM 엘리먼트를 반환하는 `render()`와 헷갈리지 않도록 합니다. [ReactDOM.render()](/react/docs/top-level-api-ko-KR.html#reactdom.render)는 컴포넌트의 **지원 인스턴스(backing instance)**에 대한 참조를 반환 합니다. [상태를 가지지 않는 컴포넌트](/react/docs/reusable-components-ko-KR.html#stateless-functions)에 대해선 `null`을 반환하죠.
|
||||
|
||||
|
||||
```js
|
||||
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
|
||||
```
|
||||
|
||||
명심하세요. 위의 코드는 컴포넌트 인스턴스를 반환하지 않습니다! 이는 그저 **ReactElement**:React에 마운트된 컴포넌트가 어떻게 보여야 할지 알려주는 경량의 표상(representation) 입니다.
|
||||
|
||||
```js
|
||||
var myComponentElement = <MyComponent />; // 이건 그냥 ReactElement 입니다.
|
||||
|
||||
한번 살펴보죠. 이 예제에서 우리는 시간이 지남에 따라 props에서 추론할 수 없는 무언가를 입력하도록 "알려주길" 원했습니다. 이 사례에서 우리는 이제 포커스 되도록 "알려주길" 원합니다. 그러나 몇 가지 문제가 있습니다. `render()`에서 반환된 것은 "자식" 컴포넌트의 실제 구성이 아니고, 단지 특정 시점의 인스턴스의 자식에 대한 *서술*일 뿐입니다. - 말하자면 스냅샷인 것이지요.
|
||||
// 여기 코드가 위치합니다...
|
||||
|
||||
var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
|
||||
myComponentInstance.doSomething();
|
||||
```
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 기억하세요, `render()`에서 반환된 것은 *실제* 자식 인스턴스가 아닙니다. 단지 특정 시점의 컴포넌트의 하위 계층구조에 있는 자식 인스턴스의 *서술*일 뿐입니다.
|
||||
> 이는 오직 최상위 레벨에서만 사용되어야 합니다. 컴포넌트의 내부에서는 `props`와 `state`가 자식 컴포넌트와 통신하도록 하거나 문자열이나 콜백 어트리뷰트 등 ref를 얻어오는 다른 방법을 사용하도록 하세요.
|
||||
|
||||
## ref 콜백 어트리뷰트
|
||||
|
||||
React는 어떤 컴포넌트에든 추가할 수 있는 특별한 어트리뷰트를 제공합니다. `ref` 어트리뷰트는 콜백 함수일 수 있으며 이는 컴포넌트가 마운트 된 후 즉시 실행됩니다. 참조된 컴포넌트는 파라미터로 전달될 것이며 콜백 함수는 즉시, 혹은 미래에 사용하기 위해 컴포넌트의 참조를 저장합니다.
|
||||
|
||||
이는 `render()`에서 반환된 무언가를 "계속 유지할 수" 없으며 아무런 의미도 없을 것이라는 뜻입니다.
|
||||
`render`에서 반환되는 무엇에든 `ref` 어트리뷰트를 추가하는 것은 간단합니다:
|
||||
|
||||
```javascript
|
||||
// 안티패턴: 이것은 동작하지 않습니다.
|
||||
```js
|
||||
render: function() {
|
||||
var myInput = <input />; // 여기서 메소드를 호출할 겁니다.
|
||||
this.rememberThisInput = myInput; // 언젠가 미래의 특정 시점에 입력할 거에요! YAY!
|
||||
return (
|
||||
<div>
|
||||
<div>...</div>
|
||||
{myInput}
|
||||
</div>
|
||||
<TextInput
|
||||
ref={function(input) {
|
||||
if (input != null) {
|
||||
input.focus();
|
||||
}
|
||||
}} />
|
||||
);
|
||||
}
|
||||
},
|
||||
```
|
||||
ES6 화살표 함수를 사용한다면 다음과 같습니다:
|
||||
|
||||
```js
|
||||
render: function() {
|
||||
return <TextInput ref={(c) => this._input = c} />;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
```
|
||||
|
||||
이 예제에서 `<input />`은 단지 `<input />`의 *서술*일 뿐입니다. 이 서술은 `<input />`에 대한 *진짜* **지원 인스턴스(backing instance)**를 생성하는 데 사용됩니다.
|
||||
`<div />` 같은 DOM 컴포넌트에 ref를 추가하면 DOM 노드를 얻게 됩니다; `<TextInput />` 같은 합성 컴포넌트에 ref를 추가하면 React 클래스 인스턴스를 얻게 됩니다. 후자의 경우, 클래스에 정의되어 있는 노출된 메소드를 호출할 수 있습니다.
|
||||
|
||||
자 그럼 어떻게 *진짜* input의 지원 인스턴스를 다룰까요?
|
||||
참조된 컴포넌트가 언마운트되고 ref가 변경되면 이전의 ref는 `null`을 인수로 호출됨을 주의 하세요. 이는 첫번째 예제에서처럼 인스턴트가 저장된 경우의 메모리 누수를 방지합니다. 또한 예제와 같이 ref를 인라인 함수 표현식으로 서술하게되면 React는 모든 업데이트에 대해 다른 함수 객체를 참조하게 됩니다. ref는 컴포넌트의 인스턴스의 호출 이전에 `null` 객체와 함께 즉시 호출될 것입니다.
|
||||
|
||||
## ref 문자열 어트리뷰트
|
||||
|
||||
React는 `render()`로 출력된 컴포넌트에 추가할 수 있는 아주 특별한 프로퍼티를 지원합니다. 이 특별한 프로퍼티는 `render()`에서 반환한 모든 것들에 대해 각각에 대응하는 **지원 인스턴스**를 참조할 수 있습니다. 이는 항상 어떤 시점에서든 올바른 인스턴스를 보장합니다.
|
||||
React는 ref에 콜백 대신 문자열도 지원합니다 이런 접근은 이제 과거의 것이긴 합니다.
|
||||
|
||||
|
||||
간단합니다:
|
||||
|
||||
1. `render`에서 반환된 값을 `ref` 어트리뷰트에 할당합니다:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
2. 다른 코드(일반적으로는 이벤트 핸들러 코드)에서 `this.refs`를 통해 **지원 인스턴스**에 접근 합니다:
|
||||
|
||||
```javascript
|
||||
this.refs.myInput
|
||||
```
|
||||
```javascript
|
||||
var input = this.refs.myInput;
|
||||
var inputValue = input.value;
|
||||
var inputRect = input.getBoundingClientRect();
|
||||
```
|
||||
|
||||
`this.refs.myInput`를 호출해 컴포넌트의 DOM 노드에 접근할 수 있습니다.
|
||||
|
||||
## ref 콜백 어트리뷰트
|
||||
|
||||
`ref` 어트리뷰트는 이름 대신 콜백 함수가 될 수도 있습니다. 이 콜백은 컴포넌트가 마운트 된 뒤 즉시 실행될 것입니다. 참조된 컴포넌트는 매개 변수로 전달되며 콜백은 이를 즉시 사용하거나, 앞으로 사용하기 위해 참조를 저장해 놓거나, 혹은 둘 다 할 것입니다.
|
||||
|
||||
`render`에서 반환한 모든 것에 간단하게 `ref` 어트리뷰트를 할당할 수 있습니다:
|
||||
|
||||
```html
|
||||
<input ref={ function(component){component.focus();} } />
|
||||
```
|
||||
|
||||
## 예제 완성하기
|
||||
## 최종 예제
|
||||
React 컴포넌트의 참조를 얻기 위해서, 현재의 React 컴포넌트를 위해서는 `this`를, 소유한 컴포넌트에 대해서는 ref를 사용할 수 있습니다. 다음과 같이 작동 합니다:
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
// input을 비워준다
|
||||
this.setState({userInput: ''}, function() {
|
||||
// 이 코드는 컴포넌트가 다시 렌더 된 다음 실행됩니다
|
||||
this.refs.theInput.focus(); // 짠! 포커스 됨!
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
클릭해서 초기화하고 포커스주기
|
||||
</div>
|
||||
<input
|
||||
ref="theInput"
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// 명시적으로 텍스트 인풋에 포커스하기 위해 raw DOM API를 사용합니다.
|
||||
this.myTextInput.focus();
|
||||
},
|
||||
render: function() {
|
||||
// ref 어트리뷰트는 컴포넌트가 마운트되면
|
||||
// this.refs에 컴포넌트에 대한 참조를 추가합니다.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref={(ref) => this.myTextInput = ref} />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
이 예제에서 render 함수는 `<input />` 인스턴스의 서술을 반환했지만, 진짜 인스턴스는 `this.refs.theInput`을 통해 접근할 수 있었습니다. `render`에서 `ref="theInput"`을 가진 컴포넌트가 반환된 동안, `this.refs.theInput`은 적절한 인스턴스에 접근합니다. 이는 `<Typeahead ref="myTypeahead" />`처럼 DOM이 아닌 고수준의 컴포넌트에서도 동작합니다.
|
||||
이 예제에서, 텍스트 인풋의 **지원 인스턴스**에 대한 참조를 얻었으며 버튼이 클릭되었을때 `focus()`를 호출했습니다.
|
||||
|
||||
합성 컴포넌트에서는 참조는 컴포넌트 클래스의 인스턴스를 가리키기 때문에 클래스에 정의된 어떤 메소드도 호출할 수 있습니다. 컴포넌트의 기저에 있는 DOM 노드에 접근하기 위해서는 [ReactDOM.findDOMNode](/react/docs/top-level-api-ko-KR.html#reactdom.finddomnode)를 "탈출구"로 사용할 수 있습니다. 하지만 이는 캡슐화를 깨며, 대부분의 경우 React 모델을 이용해 더 명확한 방법으로 구조를 짤 수 있기 때문에 추천하지 않습니다.
|
||||
|
||||
|
||||
## 요약
|
||||
|
||||
@@ -139,12 +127,13 @@ Refs는 반응적인 `props`와 `state` 스트리밍을 통해서는 불편했
|
||||
|
||||
### 이점:
|
||||
|
||||
- 컴포넌트 클래스에 public 메소드(ex. Typeahead의 reset)를 선언할 수 있으며 refs를 통해 그를 호출할 수 있습니다. (ex. `this.refs.myTypeahead.reset()`)
|
||||
- DOM을 측정하기 위해서는 거의 항상 `<input />` 같은 "기본" 컴포넌트를 다루고 `this.refs.myInput`를 통해 그 기저의 DOM 노드에 접근해야 합니다. Refs는 이 일을 확실하게 수행하는 몇 안 되는 실용적인 방법의 하나입니다.
|
||||
- 컴포넌트 클래스에 public 메소드(ex. Typeahead의 reset)를 선언할 수 있으며 refs를 통해 그를 호출할 수 있습니다. (ex. `this.refs.myTypeahead.reset()`) 대부분, 이는 선언적으로 refs를 사용하는 것보다 내장 React 데이터 흐름을 명확하게 합니다.
|
||||
- DOM을 측정하기 위해서는 거의 항상 `<input />` 같은 "기본" 컴포넌트를 다루고 ref를 통해 그 기저의 DOM 노드에 접근해야 합니다. Refs는 이 일을 확실하게 수행하는 몇 안 되는 실용적인 방법의 하나입니다.
|
||||
- Refs는 자동으로 관리합니다! 자식이 파괴되면, 그의 ref도 마찬가지로 파괴됩니다. 참조를 유지하기 위해 뭔가 미친 짓을 하지 않는 한, 메모리 걱정은 하지 않아도 됩니다.
|
||||
|
||||
### 주의:
|
||||
|
||||
- 컴포넌트의 렌더 메소드에서는, 혹은 컴포넌트의 렌더 메소드가 콜스택 어디에서든 실행되는 동안에는 절대 접근하지 마세요.
|
||||
- Google Closure Compiler에서의 분쇄 복원력 유지(to preserve Crushing resilience)를 위해서는 문자열로 정의한 것을 절대 프로퍼티로 접근하지 마세요. ref가 ref="myRefString"으로 정의되어 있다면 this.refs['myRefString']으로만 접근해야 한다는 이야기 입니다.
|
||||
- Google Closure Compiler에서의 어드벤스드 모드 분쇄 복원력 유지(to preserve advanced-mode crushing resilience)를 위해서는 문자열로 정의한 것을 절대 프로퍼티로 접근하지 마세요. ref가 ref="myRefString"으로 정의되어 있다면 this.refs['myRefString']으로만 접근해야 한다는 이야기 입니다.
|
||||
- React로 앱을 여럿 만들어 본 경험이 없다면, 보통은 처음엔 앱에서 "무언가 일어나도록" 하는데 refs를 사용하게 될 것입니다. 이 경우, 잠시 시간을 내어 `state`가 컴포넌트 계층구조의 어느 부분에서 관리되어야 할지 비판적으로 생각해 봅시다. 대개는 state가 계층구조의 더 높은 레벨에서 "소유"하는 것이 타당함이 명확해집니다. 그렇게 함으로써 `ref`를 사용해 "무언가 일어나도록" 하려는 욕망이 대부분 제거됩니다. - 대신에 데이터 플로우를 통해 대개 원하는 바를 달성하게 될 것입니다.
|
||||
- Refs는 [상태를 가지지 않는 함수](/react/docs/reusable-components-ko-KR.html#stateless-functions)에 붙일 수 없습니다. 왜냐하면 컴포넌트가 내부 인스턴스를 가지지 않기 때문입니다. 상태를 가지지 않는 컴포넌트는 항상 일반 컴포넌트로 감싸 ref를 조합 컴포넌트에 붙일 수 있습니다.
|
||||
|
||||
@@ -23,7 +23,7 @@ next: addons-ko-KR.html
|
||||
|
||||
### 브라우저에서 JSX 변환
|
||||
|
||||
JSX를 사용하신다면, [다운로드 페이지](/react/downloads.html)에서 브라우저 JSX 변환기를 제공합니다. 간단히 `<script type="text/jsx">`를 넣으면 JSX 변환기가 작동합니다.
|
||||
JSX를 사용하신다면, Babel에서 browser.js라는 [개발용 브라우저 ES6, JSX 변환기](http://babeljs.io/docs/usage/browser/)를 제공합니다. 이는 `babel-core`의 npm 릴리스나 [CDNJS](http://cdnjs.com/libraries/babel-core)로 넣을 수 있습니다. `<script type="text/babel">`를 넣으면 JSX 변환기가 작동합니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
@@ -32,12 +32,48 @@ JSX를 사용하신다면, [다운로드 페이지](/react/downloads.html)에서
|
||||
|
||||
### 상용화하기: 미리 컴파일된 JSX
|
||||
|
||||
[npm](https://www.npmjs.com/) 모듈을 가지고 있다면, 간단히 `npm install -g react-tools`를 실행해 커맨드 라인 `jsx` 툴을 설치할 수 있습니다. 이 툴은 JSX 구문을 일반적인 JavaScript파일로 변환해 브라우져에서 바로 실행할 수 있도록 합니다. 디렉터리를 감시해 파일이 변경되었을 때 자동으로 변환하도록 할 수도 있습니다. 예를 들면 `jsx --watch src/ build/` 이렇게요.
|
||||
[npm](https://www.npmjs.com/) 모듈을 가지고 있다면, `npm install -g babel-cli`를 실행할 수 있습니다. Babel은 React v0.12이상을 내장 지원합니다. 태그는 자동적으로 동등한 `React.createElement(...)`로 변환되며, `displayName`은 모든 `React.createClass` 호출에 자동으로 추론, 추가됩니다.
|
||||
|
||||
기본적으로는 JSX 파일들은 `.js` 확장자로 변환됩니다. `jsx --extension jsx src/ build/`를 사용해 `.jsx` 확장자로 파일들을 변환할 수 있습니다.
|
||||
이 툴은 JSX 구문을 일반적인 JavaScript파일로 변환해 브라우져에서 바로 실행할 수 있도록 합니다. 디렉터리를 감시해 파일이 변경되었을 때 자동으로 변환하도록 할 수도 있습니다. 예를 들면 `babel --watch src/ --out-dir lib/` 이렇게요.
|
||||
|
||||
이 툴을 어떻게 사용하는지 더 자세하게 알고싶으시면 `jsx --help`를 실행해 보세요.
|
||||
Babel 6부터 기본값으로 변환기가 포함되지 않게 되었습니다. 이는 `babel` 명령을 실행할 때나 `.babelrc`에 반드시 옵션을 지정해야 한다는 뜻입니다. React를 사용할 때 가장 일반적인 방법은 `es2015`, `react` 프리셋을 사용하는 것입니다. Babel의 변경에 대한 좀 더 자세한 정보는 [블로그에 올라온 Babel 6 공지 글](http://babeljs.io/blog/2015/10/29/6.0.0/)을 읽어보세요.
|
||||
|
||||
ES2015 문법과 React를 사용하려 할 경우의 예제입니다.
|
||||
|
||||
```
|
||||
npm install babel-preset-es2015 babel-preset-react
|
||||
babel --presets es2015,react --watch src/ --out-dir lib/
|
||||
```
|
||||
|
||||
기본적으로는 JSX 파일들은 `.js` 확장자로 변환됩니다. 바벨을 어떻게 사용하는지 더 자세하게 알고싶으시면 `babel --help`를 실행해 보세요.
|
||||
|
||||
출력 예:
|
||||
|
||||
```
|
||||
$ cat test.jsx
|
||||
var HelloMessage = React.createClass({
|
||||
render: function() {
|
||||
return <div>Hello {this.props.name}</div>;
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(<HelloMessage name="John" />, mountNode);
|
||||
$ babel test.jsx
|
||||
"use strict";
|
||||
var HelloMessage = React.createClass({
|
||||
displayName: "HelloMessage",
|
||||
render: function render() {
|
||||
return React.createElement(
|
||||
"div",
|
||||
null,
|
||||
"Hello ",
|
||||
this.props.name
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
|
||||
```
|
||||
|
||||
### 도움되는 오픈소스 프로젝트들
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ prev: tooling-integration-ko-KR.html
|
||||
next: animation-ko-KR.html
|
||||
---
|
||||
|
||||
`React.addons`은 React 앱을 만드는 데 유용한 유틸리티를 두는 곳입니다. **실험적인 기능으로 취급해야 하지만** 결국 코어나 유틸리티 라이브러리에 포함될 예정입니다.
|
||||
React 애드온은 React 앱을 만드는 데 유용한 유틸리티의 모음입니다. **실험적인 기능으로 취급해야 하고** 코어보다 더 자주 변경될 수 있습니다.
|
||||
|
||||
- [`TransitionGroup` 과 `CSSTransitionGroup`](animation-ko-KR.html)은 예를 들면 컴포넌트 삭제 직전의 트랜지션 처럼, 구현하기 까다로운 애니메이션과 트랜지션을 다룹니다.
|
||||
- [`LinkedStateMixin`](two-way-binding-helpers-ko-KR.html)는 사용자 입력과 컴포넌트의 state사이의 조정(coordination)을 단순화 합니다.
|
||||
@@ -20,6 +20,4 @@ next: animation-ko-KR.html
|
||||
- [`TestUtils`](test-utils-ko-KR.html)는 테스트 케이스를 적기 위한 간단한 헬퍼입니다. (압축되지 않은 빌드에서만 사용가능)
|
||||
- [`Perf`](perf-ko-KR.html)는 성능을 측정하고, 최적화를 위한 힌트를 제공합니다.
|
||||
|
||||
애드온을 쓰려면, 보통 `react.js` 대신 `react-with-addons.js`(혹은 압축판)을 사용해야 합니다.
|
||||
|
||||
npm을 이용해 React 패키지를 설치해 사용한다면, 그냥 `require('react')` 대신 `require('react/addons')`을 사용해 모든 애드온을 쓸 수 있습니다.
|
||||
애드온을 쓰려면, npm에서 각각 설치하세요.(예를 들면, `npm install react-addons-pure-render-mixin`) npm을 사용하지 않는 애드온 사용법에 대한 지원은 없습니다.
|
||||
|
||||
@@ -18,7 +18,7 @@ React에는 애니메이션을 위한 저 수준 API로 `ReactTransitionGroup`
|
||||
`ReactCSSTransitionGroup`은 `ReactTransitions`을 위한 인터페이스입니다. 이는 애니메이션을 제어할 모든 컴포넌트를 감싸는 하나의 엘리먼트 입니다. 아래는 목록의 아이템을 페이드 인/아웃하는 간단한 예제입니다.
|
||||
|
||||
```javascript{28-30}
|
||||
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
|
||||
var TodoList = React.createClass({
|
||||
getInitialState: function() {
|
||||
@@ -45,7 +45,7 @@ var TodoList = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.handleAdd}>Add Item</button>
|
||||
<ReactCSSTransitionGroup transitionName="example">
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300} >
|
||||
{items}
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
@@ -53,9 +53,10 @@ var TodoList = React.createClass({
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> `ReactCSSTransitionGroup`의 모든 자식은 [`key` 어트리뷰트](/react/docs/multiple-components-ko-KR.html#dynamic-children)를 반드시 만들어야 합니다. 한 아이템을 렌더한다 해도 예외는 아닙니다. 키는 React가 어떤 자식이 들어오고, 나가고, 머무르는지 파악할 때 사용합니다.
|
||||
> `ReactCSSTransitionGroup`의 모든 자식은 [`key` 어트리뷰트](/react/docs/multiple-components-ko-KR.html#dynamic-children)를 반드시 만들어야 합니다. 한 아이템을 렌더할 때도 예외는 아닙니다. 키는 React가 어떤 자식이 들어오고, 나가고, 머무르는지 파악할 때 사용합니다.
|
||||
|
||||
이 컴포넌트에서 새로운 아이템이 `ReactCSSTransitionGroup`에 추가되면 `example-enter` 아이템은 CSS 클래스를 가지게 되고 다음 순간에 `example-enter-active` CSS 클래스가 추가됩니다. 이는 `transitionName` prop을 기반으로 한 관례입니다.
|
||||
|
||||
@@ -68,23 +69,21 @@ var TodoList = React.createClass({
|
||||
|
||||
.example-enter.example-enter-active {
|
||||
opacity: 1;
|
||||
transition: opacity .5s ease-in;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
```
|
||||
|
||||
`ReactCSSTransitionGroup`에서 아이템을 제거하려해도 DOM에는 남게 됩니다. 만약 애드온을 React의 최소화하지 않은 빌드와 사용한다면, 애니메이션이나 트랜지션이 일어나는 것을 예상하고 있었다는 React의 경고를 보게 될 것입니다. 그게 바로 `ReactCSSTransitionGroup`가 DOM 엘리먼트를 애니메이션이 끝날 때까지 페이지에 남겨두는 이유입니다. 이 CSS를 넣어보세요.
|
||||
|
||||
```css
|
||||
.example-leave {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.example-leave.example-leave-active {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
```
|
||||
|
||||
에니메이션 기간이 CSS와 렌더 메소드 양쪽에 지정될 필요가 있다는 것에 주의하셔야 합니다. 이는 엘리먼트에서 애니메이션 클래스를 제거할 때 (만약 남아있다면) DOM에서 엘리먼트를 제거할 때 React에 알려줍니다.
|
||||
|
||||
### 처음 마운트에서 애니메이션 하기
|
||||
|
||||
`ReactCSSTransitionGroup`은 컴포넌트를 처음 마운트할 때 추가 트렌지션 단계를 추가하기 위해, 선택적인 prop `transitionAppear`를 제공합니다. 일반적으로 처음 마운트할 때 트렌지션 단계를 넣지 않기 때문에 `transitionAppear`의 기본 값은 `false`입니다. 뒤의 예제는 `transitionAppear` prop에 `true` 값을 넘기고 있습니다.
|
||||
@@ -92,7 +91,7 @@ var TodoList = React.createClass({
|
||||
```javascript{3-5}
|
||||
render: function() {
|
||||
return (
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true}>
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
|
||||
<h1>Fading at Initial Mount</h1>
|
||||
</ReactCSSTransitionGroup>
|
||||
);
|
||||
@@ -104,11 +103,11 @@ var TodoList = React.createClass({
|
||||
```css
|
||||
.example-appear {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
|
||||
.example-appear.example-appear-active {
|
||||
opacity: 1;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -125,23 +124,23 @@ var TodoList = React.createClass({
|
||||
```javascript
|
||||
...
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName={
|
||||
transitionName={ {
|
||||
enter: 'enter',
|
||||
enterActive: 'enterActive',
|
||||
leave: 'leave',
|
||||
leaveActive: 'leaveActive',
|
||||
appear: 'appear',
|
||||
appearActive: 'appearActive'
|
||||
}>
|
||||
} }>
|
||||
{item}
|
||||
</ReactCSSTransitionGroup>
|
||||
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName={
|
||||
transitionName={ {
|
||||
enter: 'enter',
|
||||
leave: 'leave',
|
||||
appear: 'appear'
|
||||
}>
|
||||
} }>
|
||||
{item2}
|
||||
</ReactCSSTransitionGroup>
|
||||
...
|
||||
@@ -176,7 +175,7 @@ var TodoList = React.createClass({
|
||||
위의 예제에서 `ReactCSSTransitionGroup`에 아이템 목록을 렌더했지만, `ReactCSSTransitionGroup`의 자식은 하나이거나 없을 수도 있습니다. 이는 한 엘리먼트가 들어오고 나가는 것의 애니메이션을 가능하게 합니다. 비슷하게, 현재 엘리먼트가 나가는 동안 새 앨리먼트의 애니메이션을 하면, 새 엘리먼트가 현재 엘리먼트를 교체하는 애니메이션을 만들 수 있습니다. 예를 들어 이렇게 간단한 이미지 회전 베너(carousel)를 구현할 수 있습니다.
|
||||
|
||||
```javascript{10-12}
|
||||
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
|
||||
var ImageCarousel = React.createClass({
|
||||
propTypes: {
|
||||
@@ -185,7 +184,7 @@ var ImageCarousel = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ReactCSSTransitionGroup transitionName="carousel">
|
||||
<ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}>
|
||||
<img src={this.props.imageSrc} key={this.props.imageSrc} />
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
@@ -204,7 +203,7 @@ var ImageCarousel = React.createClass({
|
||||
|
||||
## 저수준 API: `ReactTransitionGroup`
|
||||
|
||||
`ReactTransitionGroup`은 애니메이션의 기초입니다. 이는 `React.addons.TransitionGroup`으로 접근할 수 있습니다. 위에 있는 예제처럼 자식들이 선언적으로 여기에 추가되거나 삭제되는 경우, 특별한 훅이 이 생명주기에서 호출됩니다.
|
||||
`ReactTransitionGroup`은 애니메이션의 기초입니다. 이는 `require('react-addons-transition-group')`으로 접근할 수 있습니다. 위의 예제처럼 자식들이 선언적으로 여기에 추가되거나 삭제되는 경우, 특별한 훅이 이 생명주기에서 호출됩니다.
|
||||
|
||||
### `componentWillAppear(callback)`
|
||||
|
||||
@@ -240,11 +239,7 @@ var ImageCarousel = React.createClass({
|
||||
</ReactTransitionGroup>
|
||||
```
|
||||
|
||||
모든 React가 렌더할 수 있는 DOM 컴포넌트는 사용할 수 있습니다. 하지만 `component`가 DOM 컴포넌트일 필요는 없습니다. React 컴포넌트라면 무엇이든 넣을 수 있습니다. 직접 구현한 컴포넌트여도 됩니다!
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> v0.12이전에는, DOM 컴포넌트를 사용할 때, `component` prop은 `React.DOM.*`로 참조할 필요가 있었습니다. 이제 컴포넌트가 단순히 `React.createElement`로 전달되기 때문에, `component` prop은 스트링이어야 합니다. 복합 컴포넌트는 팩토리를 넘겨야 합니다.
|
||||
React가 렌더할 수 있는 DOM 컴포넌트는 전부 사용할 수 있습니다. 하지만 `component`가 DOM 컴포넌트일 필요는 없습니다. React 컴포넌트라면 무엇이든 넣을 수 있습니다. 직접 구현한 컴포넌트여도 됩니다! 그냥 `component={List}`를 적으면 컴포넌트는 `this.props.children`로 받을 수 있습니다.
|
||||
|
||||
사용자 정의를 포함한 어떤 프로퍼티도 렌더된 컴포넌트의 프로퍼티가 됩니다. 예를 들어, `<ul>`에 CSS 클래스를 넣어서 렌더하려면 이렇게 하면 됩니다.
|
||||
|
||||
|
||||
@@ -45,9 +45,11 @@ var NoLink = React.createClass({
|
||||
|
||||
이것은 정말 잘 동작하고, 데이터가 어떻게 흐르는지 매우 명확하게 보여지지만, 폼필드가 많을 경우 약간 장황해 질 수 있습니다. 타이핑을 줄이기 위해 `ReactLink`를 사용해 보겠습니다.
|
||||
|
||||
```javascript{2,7}
|
||||
```javascript{4,9}
|
||||
var LinkedStateMixin = require('react-addons-linked-state-mixin');
|
||||
|
||||
var WithLink = React.createClass({
|
||||
mixins: [React.addons.LinkedStateMixin],
|
||||
mixins: [LinkedStateMixin],
|
||||
getInitialState: function() {
|
||||
return {message: 'Hello!'};
|
||||
},
|
||||
@@ -66,7 +68,6 @@ checkbox의 `value` 어트리뷰트는 다른 것과 다르게 checkbox가 체
|
||||
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
|
||||
```
|
||||
|
||||
|
||||
## 내부 구조
|
||||
|
||||
`ReactLink`에는 크게 인스턴스를 생성하는 면과 사용하는 면이 있습니다. `ReactLink`가 얼마나 간단한지 확인하기 위해, 이 부분들을 보다 명시적으로 고쳐 봅시다.
|
||||
@@ -96,8 +97,10 @@ var WithoutMixin = React.createClass({
|
||||
### valueLink 없이 ReactLink 쓰기
|
||||
|
||||
```javascript
|
||||
var LinkedStateMixin = require('react-addons-linked-state-mixin');
|
||||
|
||||
var WithoutLink = React.createClass({
|
||||
mixins: [React.addons.LinkedStateMixin],
|
||||
mixins: [LinkedStateMixin],
|
||||
getInitialState: function() {
|
||||
return {message: 'Hello!'};
|
||||
},
|
||||
|
||||
@@ -6,6 +6,6 @@ prev: two-way-binding-helpers.html
|
||||
next: test-utils.html
|
||||
---
|
||||
|
||||
> NOTE:
|
||||
> 주의:
|
||||
>
|
||||
> This module has been deprecated; use [JedWatson/classnames](https://github.com/JedWatson/classnames) instead.
|
||||
> 이 모듈은 폐기예정입니다. 대신 [JedWatson/classnames](https://github.com/JedWatson/classnames)를 사용하세요.
|
||||
|
||||
@@ -6,39 +6,66 @@ prev: two-way-binding-helpers-ko-KR.html
|
||||
next: clone-with-props-ko-KR.html
|
||||
---
|
||||
|
||||
`React.addons.TestUtils`는 선택한 테스트 프레임워크(React는 [Jest](https://facebook.github.io/jest/)를 사용)에서 React 컴포넌트를 테스트하기 쉽게 합니다.
|
||||
`ReactTestUtils`는 선택한 테스트 프레임워크(React는 [Jest](https://facebook.github.io/jest/)를 사용)에서 React 컴포넌트를 테스트하기 쉽게 합니다.
|
||||
|
||||
```
|
||||
var ReactTestUtils = require('react-addons-test-utils');
|
||||
```
|
||||
|
||||
### Simulate
|
||||
|
||||
```javascript
|
||||
Simulate.{eventName}(DOMElement element, object eventData)
|
||||
Simulate.{eventName}(
|
||||
DOMElement element,
|
||||
[object eventData]
|
||||
)
|
||||
```
|
||||
|
||||
DOM 노드에 이벤트 디스패치하는 것을 시뮬레이트합니다. 선택적으로 `eventData`를 통해 이벤트 데이터도 처리할 수 있습니다. **아마 `ReactTestUtils`에서 가장 유용한 유틸리티일 것 입니다.**
|
||||
|
||||
사용 예:
|
||||
**엘리먼트 클릭**
|
||||
|
||||
```javascript
|
||||
var node = ReactDOM.findDOMNode(this.refs.input);
|
||||
React.addons.TestUtils.Simulate.click(node);
|
||||
React.addons.TestUtils.Simulate.change(node, {target: {value: 'Hello, world'}});
|
||||
React.addons.TestUtils.Simulate.keyDown(node, {key: "Enter"});
|
||||
// <button ref="button">...</button>
|
||||
var node = this.refs.button;
|
||||
ReactTestUtils.Simulate.click(node);
|
||||
```
|
||||
|
||||
**입력 필드의 값을 변경하고 엔터 누르기.**
|
||||
|
||||
```javascript
|
||||
// <input ref="input" />
|
||||
var node = this.refs.input;
|
||||
node.value = 'giraffe'
|
||||
ReactTestUtils.Simulate.change(node);
|
||||
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
|
||||
```
|
||||
|
||||
*컴포넌트에서 사용할 이벤트 프로퍼티(예를 들어 keyCode, which, 등등...)는 React에서 만들어 주지 않으므로 직접 제공해야 합니다.*
|
||||
|
||||
`Simulate`에는 React가 이해하는 모든 이벤트에 대해 메소드가 있습니다.
|
||||
|
||||
### renderIntoDocument
|
||||
|
||||
```javascript
|
||||
ReactComponent renderIntoDocument(ReactElement instance)
|
||||
ReactComponent renderIntoDocument(
|
||||
ReactElement instance
|
||||
)
|
||||
```
|
||||
|
||||
문서의 detach된 DOM 노드에 컴포넌트를 렌더합니다. **이 기능은 DOM을 필요로 합니다.**
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> React를 임포트하기 **전에** `window`, `window.document`, `window.document.createElement`을 전역적으로 사용가능하게 해두어야 합니다. 아니면 React는 DOM과 `setState`같은 메소드가 동작하지 않는다고 생각할 수 있습니다.
|
||||
|
||||
### mockComponent
|
||||
|
||||
```javascript
|
||||
object mockComponent(function componentClass, string? mockTagName)
|
||||
object mockComponent(
|
||||
function componentClass,
|
||||
[string mockTagName]
|
||||
)
|
||||
```
|
||||
|
||||
목 컴포넌트 모듈을 이 메소드에 넘겨 더미 React 컴포넌트로 사용할 수 있도록 합니다. 이 더미는 유용한 메소드와 함께 사용해 기능을 보강할 수 있습니다. 일반적인 렌더링과는 다르게, 컴포넌트는 제공된 자식을 포함하는 평범한 `<div>`가 됩니다. (`mockTagName`을 통해 div가 아닌 다른 태그를 지정해 줄 수도 있습니다.)
|
||||
@@ -46,7 +73,9 @@ object mockComponent(function componentClass, string? mockTagName)
|
||||
### isElement
|
||||
|
||||
```javascript
|
||||
boolean isElement(ReactElement element)
|
||||
boolean isElement(
|
||||
ReactElement element
|
||||
)
|
||||
```
|
||||
|
||||
`element`가 ReactElement면 `true`를 리턴합니다.
|
||||
@@ -54,7 +83,10 @@ boolean isElement(ReactElement element)
|
||||
### isElementOfType
|
||||
|
||||
```javascript
|
||||
boolean isElementOfType(ReactElement element, function componentClass)
|
||||
boolean isElementOfType(
|
||||
ReactElement element,
|
||||
function componentClass
|
||||
)
|
||||
```
|
||||
|
||||
`element`가 React `componentClass` 타입인 ReactElement면 `true`를 리턴합니다.
|
||||
@@ -62,7 +94,9 @@ boolean isElementOfType(ReactElement element, function componentClass)
|
||||
### isDOMComponent
|
||||
|
||||
```javascript
|
||||
boolean isDOMComponent(ReactComponent instance)
|
||||
boolean isDOMComponent(
|
||||
ReactComponent instance
|
||||
)
|
||||
```
|
||||
|
||||
`instance`가 (`<div>`나 `<span>`같은) DOM 컴포넌트면 `true`를 리턴합니다.
|
||||
@@ -78,7 +112,10 @@ boolean isCompositeComponent(ReactComponent instance)`
|
||||
### isCompositeComponentWithType
|
||||
|
||||
```javascript
|
||||
boolean isCompositeComponentWithType(ReactComponent instance, function componentClass)
|
||||
boolean isCompositeComponentWithType(
|
||||
ReactComponent instance,
|
||||
function componentClass
|
||||
)
|
||||
```
|
||||
|
||||
`instance`가 (`React.createClass()`로 생성된) 복합 컴포넌트고 React `componentClass` 타입이면 `true`를 리턴합니다.
|
||||
@@ -86,7 +123,10 @@ boolean isCompositeComponentWithType(ReactComponent instance, function component
|
||||
### findAllInRenderedTree
|
||||
|
||||
```javascript
|
||||
array findAllInRenderedTree(ReactComponent tree, function test)
|
||||
array findAllInRenderedTree(
|
||||
ReactComponent tree,
|
||||
function test
|
||||
)
|
||||
```
|
||||
|
||||
`tree`안의 모든 컴포넌트에서 `test(component)`가 `true`인 모든 컴포넌트를 모읍니다. 이것만으로는 그렇게 유용하지 않습니다만, 다른 테스트 유틸와 같이 사용합니다.
|
||||
@@ -94,7 +134,9 @@ array findAllInRenderedTree(ReactComponent tree, function test)
|
||||
### scryRenderedDOMComponentsWithClass
|
||||
|
||||
```javascript
|
||||
array scryRenderedDOMComponentsWithClass(ReactComponent tree, string className)
|
||||
array scryRenderedDOMComponentsWithClass(
|
||||
ReactComponent tree, string className
|
||||
)
|
||||
```
|
||||
렌더된 트리의 모든 컴포넌트 인스턴스 중에서 클래스 이름이 `className`인 DOM 컴포넌트들을 찾습니다.
|
||||
|
||||
@@ -109,7 +151,10 @@ ReactComponent findRenderedDOMComponentWithClass(ReactComponent tree, string cla
|
||||
### scryRenderedDOMComponentsWithTag
|
||||
|
||||
```javascript
|
||||
array scryRenderedDOMComponentsWithTag(ReactComponent tree, string tagName)
|
||||
array scryRenderedDOMComponentsWithTag(
|
||||
ReactComponent tree,
|
||||
string tagName
|
||||
)
|
||||
```
|
||||
|
||||
렌더된 트리의 모든 컴포넌트 인스턴스중에서 태그 이름이 `tagName`인 DOM 컴포넌트들을 찾습니다.
|
||||
@@ -117,7 +162,10 @@ array scryRenderedDOMComponentsWithTag(ReactComponent tree, string tagName)
|
||||
### findRenderedDOMComponentWithTag
|
||||
|
||||
```javascript
|
||||
ReactComponent findRenderedDOMComponentWithTag(ReactComponent tree, string tagName)
|
||||
ReactComponent findRenderedDOMComponentWithTag(
|
||||
ReactComponent tree,
|
||||
string tagName
|
||||
)
|
||||
```
|
||||
|
||||
`scryRenderedDOMComponentsWithTag()`와 비슷하지만 하나의 결과만 기대될 때 사용합니다. 하나의 결과를 리턴하거나 한개 이상의 결과가 나온 경우에는 예외를 던집니다.
|
||||
@@ -125,7 +173,10 @@ ReactComponent findRenderedDOMComponentWithTag(ReactComponent tree, string tagNa
|
||||
### scryRenderedComponentsWithType
|
||||
|
||||
```javascript
|
||||
array scryRenderedComponentsWithType(ReactComponent tree, function componentClass)
|
||||
array scryRenderedComponentsWithType(
|
||||
ReactComponent tree,
|
||||
function componentClass
|
||||
)
|
||||
```
|
||||
|
||||
타입이 `componentClass`인 모든 컴포넌트 인스턴스를 찾습니다.
|
||||
@@ -133,7 +184,9 @@ array scryRenderedComponentsWithType(ReactComponent tree, function componentClas
|
||||
### findRenderedComponentWithType
|
||||
|
||||
```javascript
|
||||
ReactComponent findRenderedComponentWithType(ReactComponent tree, function componentClass)
|
||||
ReactComponent findRenderedComponentWithType(
|
||||
ReactComponent tree, function componentClass
|
||||
)
|
||||
```
|
||||
|
||||
`scryRenderedComponentsWithType()`와 비슷하지만 하나의 결과만 기대될 때 사용합니다. 하나의 결과를 리턴하거나 한개 이상의 결과가 나온 경우에는 예외를 던집니다.
|
||||
@@ -149,13 +202,15 @@ ReactShallowRenderer createRenderer()
|
||||
테스트에서 얕은 렌더러를 생성하고자 할때 호출합니다. 이를 이벤트와 업데이트에 스스로 반응하는 컴포넌트를 렌더하기 위한 "장소"라고 생각할 수 있습니다.
|
||||
|
||||
```javascript
|
||||
shallowRenderer.render(ReactElement element)
|
||||
shallowRenderer.render(
|
||||
ReactElement element
|
||||
)
|
||||
```
|
||||
|
||||
`ReactDOM.render`와 유사합니다.
|
||||
|
||||
```javascript
|
||||
ReactComponent shallowRenderer.getRenderOutput()
|
||||
ReactElement shallowRenderer.getRenderOutput()
|
||||
```
|
||||
|
||||
`render`가 호출 된 후, 얕게 렌더된 결과물을 반환합니다. 그 후엔 결과물에 대한 검증을 시작할 수 있습니다. 예를 들어 컴포넌트의 렌더 메소드가 다음을 반환한다면:
|
||||
|
||||
@@ -12,8 +12,10 @@ next: create-fragment-ko-KR.html
|
||||
드문 경우긴 하지만 원래 엘리먼트와 다른 prop을 가진 React 엘리먼트의 복사본을 만들고 싶을 때가 있습니다. 예를 들면 `this.props.children`에 클론한 엘리먼트를 넘기고 다른 prop으로 렌더링하는 경우 입니다.
|
||||
|
||||
```js
|
||||
var cloneWithProps = require('react-addons-clone-with-props');
|
||||
|
||||
var _makeBlue = function(element) {
|
||||
return React.addons.cloneWithProps(element, {style: {color: 'blue'}});
|
||||
return cloneWithProps(element, {style: {color: 'blue'}});
|
||||
};
|
||||
|
||||
var Blue = React.createClass({
|
||||
|
||||
@@ -18,7 +18,7 @@ var Swapper = React.createClass({
|
||||
rightChildren: React.PropTypes.node,
|
||||
|
||||
swapped: React.PropTypes.bool
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
var children;
|
||||
if (this.props.swapped) {
|
||||
@@ -33,20 +33,22 @@ var Swapper = React.createClass({
|
||||
|
||||
`swapped` prop을 변경할 경우 자식은 마운트 해제되거나 다시 마운트 될 수 있습니다. 두 자식 집합에 키가 할당되지 않았기 때문입니다.
|
||||
|
||||
이 문제를 해결하기 위해서 `React.addons.createFragment`를 사용해 자식 집합에 키를 부여할 수 있습니다.
|
||||
이 문제를 해결하기 위해서 `createFragment`를 사용해 자식 집합에 키를 부여할 수 있습니다.
|
||||
|
||||
#### `ReactFragment React.addons.createFragment(object children)`
|
||||
#### `Array<ReactNode> createFragment(object children)`
|
||||
|
||||
배열을 만드는 대신에 다음과 같이 해볼 수 있습니다:
|
||||
|
||||
```js
|
||||
var createFragment = require('react-addons-create-fragment');
|
||||
|
||||
if (this.props.swapped) {
|
||||
children = React.addons.createFragment({
|
||||
children = createFragment({
|
||||
right: this.props.rightChildren,
|
||||
left: this.props.leftChildren
|
||||
});
|
||||
} else {
|
||||
children = React.addons.createFragment({
|
||||
children = createFragment({
|
||||
left: this.props.leftChildren,
|
||||
right: this.props.rightChildren
|
||||
});
|
||||
|
||||
@@ -44,7 +44,9 @@ var newData = extend(myData, {
|
||||
`update()`는 이런 패턴 속에서 코드를 더 쉽게 쓸 수 있도록 편의 문법을 제공합니다. 코드는 이렇습니다:
|
||||
|
||||
```js
|
||||
var newData = React.addons.update(myData, {
|
||||
var update = require('react-addons-update');
|
||||
|
||||
var newData = update(myData, {
|
||||
x: {y: {z: {$set: 7}}},
|
||||
a: {b: {$push: [9]}}
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ React 컴포넌트의 렌더 함수가 "pure"하다면 (다른 말로, props나
|
||||
예제:
|
||||
|
||||
```js
|
||||
var PureRenderMixin = require('react/addons').addons.PureRenderMixin;
|
||||
var PureRenderMixin = require('react-addons-pure-render-mixin');
|
||||
React.createClass({
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@ React는 보통 처음에는 꽤 빠릅니다. 하지만 모든 성능을 짜내
|
||||
|
||||
## 일반 API
|
||||
|
||||
여기에서 설명하는 `Perf` 객체는 `react-with-addons.js`를 사용해 개발 모드에서 빌드될 때 `React.addons.Perf`로 노출됩니다.
|
||||
여기에서 설명하는 `Perf` 객체는 `require('react-addons-perf')`로 노출되고 React 개발 모드에서만 사용할 수 있습니다. 이 번들을 프로덕션에서 앱과 같이 빌드하시면 안됩니다.
|
||||
|
||||
### `Perf.start()`와 `Perf.stop()`
|
||||
측정을 시작/정지합니다. 그 사이의 React 연산은 밑에 있는 분석을 하기위해 기록됩니다. 미미한 양의 연산은 무시됩니다.
|
||||
|
||||
종료 후, 측정을 하기위해서는 이후에 설명할 `Perf.getLastMeasurements()`가 필요합니다.
|
||||
|
||||
### `Perf.printInclusive(measurements)`
|
||||
전 수행 시간을 출력합니다. 인자가 넘겨지지 않으면, 기본값은 지난 기록부터의 모든 측정이 됩니다. 이 출력은 밑에 있는 것처럼 콘솔에서 깔끔한 테이블로 그려집니다.
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ id: advanced-performance-ko-KR
|
||||
title: 성능 심화
|
||||
permalink: advanced-performance-ko-KR.html
|
||||
prev: perf-ko-KR.html
|
||||
next: context-ko-KR.html
|
||||
---
|
||||
|
||||
React를 도입하려 할 때 많은 사람이 묻는 첫 번째 질문은 React를 사용하지 않을 때처럼 애플리케이션이 빠르고 반응성도 좋을 것이냐는 것입니다. 모든 상태변화에 대해 컴포넌트의 하위 트리를 전부 다시 렌더링하는 아이디어에 대해 사람들은 이 프로세스가 성능에 부정적인 영향을 줄 것으로 생각하지만, React는 여러 가지 영리한 방법을 통해 UI를 업데이트하는데 필요한 비싼 DOM 조작을 최소화합니다.
|
||||
@@ -52,7 +53,7 @@ React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return <div>this.props.value</div>;
|
||||
return <div>{this.props.value}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
@@ -76,7 +77,7 @@ React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return <div>this.props.value.foo</div>;
|
||||
return <div>{this.props.value.foo}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
137
docs/12-context.ko-KR.md
Normal file
137
docs/12-context.ko-KR.md
Normal file
@@ -0,0 +1,137 @@
|
||||
---
|
||||
id: context
|
||||
title: 컨텍스트
|
||||
permalink: context-ko-KR.html
|
||||
prev: advanced-performance-ko-KR.html
|
||||
---
|
||||
|
||||
React의 가장 큰 장점 중 하나는 React 컴포넌트를 통해 데이터의 흐름을 추적하기 쉽다는 것입니다. 컴포넌트를 보면 각각의 프로퍼티가 어떻게 전달되었는지 쉽게 파악할 수 있습니다.
|
||||
|
||||
때때로 컴포넌트 트리를 통해 props을 전단하는 대신 수동으로 모든 레벨에서 데이터를 전달하고 싶은 경우가 있습니다. React의 "컨텍스트" 기능은 이를 가능하게 해줍니다.
|
||||
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 컨텍스트는 실험적인 고급 기능입니다. 향후 릴리즈에서 API가 변경될 수 있습니다.
|
||||
>
|
||||
> 대부분은 애플리켄이션은 컨텍스트가 필요하지 않을겁니다. 특히 React로 시작한 경우에는 컨텍스트를 사용하지 않을겁니다. 컨텍스트의 사용은 데이터 흐름을 명확하지 않게 만들기 때문에 코드를 이해하기 어려워 집니다. 이는 마치 앱에서 전역 변수를 state로 전달하는 경우와 유사합니다.
|
||||
>
|
||||
> **만약 컨텍스트를 사용해야 하는 경우에도, 가능한 아껴 사용하세요.**
|
||||
>
|
||||
> 구축하는것이 애플리케이션이든 라이브러리든간에, 가능한 컨텍스트의 사용은 작은 영역으로 격리하고 직접적으로 컨텍스트 API를 사용하는 것을 피하세요. 그렇게 하면 API가 변경 되더라도 쉽게 업데이트 할 수 있습니다.
|
||||
|
||||
## 트리를 통해 정보를 자동으로 전달하기
|
||||
|
||||
아래와 같은 구조가 있다고 가정해 봅시다:
|
||||
|
||||
```javascript
|
||||
var Button = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<button style={{'{{'}}background: this.props.color}}>
|
||||
{this.props.children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Message = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.text} <Button color={this.props.color}>삭제</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var MessageList = React.createClass({
|
||||
render: function() {
|
||||
var color = "purple";
|
||||
var children = this.props.messages.map(function(message) {
|
||||
return <Message text={message.text} color={color} />;
|
||||
});
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
이 예제에서, 우리는 스타일을 주기 위해 수동으로 적절하게 `Button`과 `Messages` 컴포넌트에 `color` 프로퍼티를 엮어서 전달했습니다. 테마는 서브트리가 정보 조각의 일부(여기선 color)에 접근하기 원하는 좋은 예제입니다. 컨텍스트를 사용하면 우리는 이를 자동으로 트리로 전달할 수 있습니다:
|
||||
|
||||
```javascript{2-4,7,18,25-30,33}
|
||||
var Button = React.createClass({
|
||||
contextTypes: {
|
||||
color: React.PropTypes.string
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<button style={{'{{'}}background: this.context.color}}>
|
||||
{this.props.children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Message = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.text} <Button>Delete</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var MessageList = React.createClass({
|
||||
childContextTypes: {
|
||||
color: React.PropTypes.string
|
||||
},
|
||||
getChildContext: function() {
|
||||
return {color: "purple"};
|
||||
},
|
||||
render: function() {
|
||||
var children = this.props.messages.map(function(message) {
|
||||
return <Message text={message.text} />;
|
||||
});
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
`childContextTypes`와 `getChildContext`를 `MessageList`(context provider)에 추가함으로써, React는 정보를 자동으로 아래로 전달하며 서브트리내의 어떤 컴포넌트든 (여기선 `Button`) `contextTypes`를 정의함으로써 이에 접근할 수 있습니다.
|
||||
|
||||
`contextTypes`가 정의되지 않은 경우, `this.context`는 빈 오브젝트가 됩니다.
|
||||
|
||||
## 부모-자식 커플링
|
||||
|
||||
컨텍스트는 다음과 같은 API를 구성할 수 있게 해줍니다:
|
||||
|
||||
```javascript
|
||||
<Menu>
|
||||
<MenuItem>가지</MenuItem>
|
||||
<MenuItem>땅콩호박</MenuItem>
|
||||
<MenuItem>클레멘타인</MenuItem>
|
||||
</Menu>
|
||||
```
|
||||
|
||||
`Menu` 컴포넌트에서 관련 정보를 전달함으로써 각각의 `MenuItem`가 부모인 `Menu` 컴포넌트와 통신할 수 있습니다.
|
||||
|
||||
**이 API를 이용해 컴포넌트를 구성하기 전에, 깔끔한 대안이 있는지 먼저 고려해 보세요.** 다음과 같이 간단히 아이템을 배열로 넘겨 보겠습니다:
|
||||
|
||||
```javascript
|
||||
<Menu items={['가지', '땅콩호박', '클레멘타인']} />
|
||||
```
|
||||
|
||||
원한다면 전체 React 컴포넌트를 프로퍼티로 전달할 수도 있습니다.
|
||||
|
||||
## 컨텍스트를 사용하지 말아야 하는 경우
|
||||
|
||||
대부분의 경우, 깔끔한 코드를 위해 전역 변수를 피하는 것과 마찬가지로 컨텍스트의 사용을 피해야 합니다. 특히 "타이핑을 줄이거나" 명시적인 프로퍼티 전달 대신 이를 사용하려는 경우 다시 한번 생각해 보세요.
|
||||
|
||||
컨텍스트의 가장 적절한 사용 사례는 로그인한 유저, 언어 설정, 테마 정보 등을 암시적으로 전달하는 것입니다. 컨텍스트를 사용함으로써 이런 정보들을 전역으로 다루는 대신 단일 React 서브트리 내에서 다룰 수 있습니다.
|
||||
|
||||
모델 데이터를 컴포넌트로 전달하는데 컨텍스트를 사용하지 마세요. 트리를 통해 명시적으로 데이터를 엮어 전달하는 것이 훨씬 이해하기 쉽습니다. 컨텍스트는 렌더되는 위치에 따라 다르게 작동하기 때문에 컴포넌트를 더욱 연결되고(coupled) 재사용성이 떨어지게 만듭니다.
|
||||
|
||||
## 알려진 한계점
|
||||
|
||||
컴포넌트에 의해 제공되는 컨텍스트의 값이 변경될 때, 중간 부모가 `shouldComponentUpdate`에서`false`을 반환한다면 그 값을 사용하는 자손은 업데이트되지 않습니다. 자세한 내용은 [#2517](https://github.com/facebook/react/issues/2517) 이슈를 확인하세요.
|
||||
@@ -15,9 +15,7 @@ React를 시작하는 가장 빠른 방법은 다음의 Hello World JSFiddle 예
|
||||
|
||||
## npm으로 React 사용하기
|
||||
|
||||
React는 CommonJS 모듈과 유사한 시스템인 [browserify](http://browserify.org/) 또는 [webpack](https://webpack.github.io/)를 사용하기를 추천합니다.
|
||||
[`react`](https://www.npmjs.com/package/react) 와 [`react-dom`](https://www.npmjs.com/package/react-dom) npm
|
||||
패키지를 이용합니다.
|
||||
[browserify](http://browserify.org/), [webpack](https://webpack.github.io/) 같은 CommonJS 모듈 시스템과 함께 React를 사용하시는 것을 권장합니다. [`react`](https://www.npmjs.com/package/react), [`react-dom`](https://www.npmjs.com/package/react-dom) npm 패키지를 사용하세요.
|
||||
|
||||
```js
|
||||
// main.js
|
||||
@@ -33,10 +31,14 @@ ReactDOM.render(
|
||||
browserify를 설치한 후에 React DOM을 설치하고 bundle을 빌드합니다.
|
||||
|
||||
```sh
|
||||
$ npm install --save react react-dom
|
||||
$ browserify -t babelify main.js -o bundle.js
|
||||
$ npm install --save react react-dom babelify babel-preset-react
|
||||
$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
|
||||
```
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> ES2015를 사용하고 있다면, `babel-preset-es2015` 패키지도 설치할 필요가 있습니다.
|
||||
|
||||
## npm 없이 Quick Start 하기
|
||||
|
||||
만약 당신이 npm을 사용할 준비가 아직 안되었다면, 미리빌드된 React와 React DOM 파일이 포함된 초심자용 키트를 다운로드 받을 수 있습니다.
|
||||
@@ -97,17 +99,21 @@ ReactDOM.render(
|
||||
먼저 [Babel](http://babeljs.io/) 커맨드라인 도구를 설치합니다. ([npm](https://www.npmjs.com/) 필요):
|
||||
|
||||
```
|
||||
npm install --global babel
|
||||
npm install --global babel-cli
|
||||
npm install babel-preset-react
|
||||
```
|
||||
|
||||
그다음, `src/helloworld.js` 파일을 일반 JavaScript 파일로 변환합니다:
|
||||
|
||||
```
|
||||
babel src --watch --out-dir build
|
||||
|
||||
babel --presets react src --watch --out-dir build
|
||||
```
|
||||
|
||||
수정할 때마다 `build/helloworld.js` 파일이 자동생성됩니다. 더 자세한 사용법은 [Babel CLI documentation](http://babeljs.io/docs/usage/cli/)를 읽어보세요.
|
||||
> 주의:
|
||||
>
|
||||
> ES2015를 사용하고 있다면, `babel-preset-es2015` 패키지도 설치할 필요가 있습니다.
|
||||
|
||||
수정할 때마다 `build/helloworld.js` 파일이 자동생성됩니다. 더 자세한 사용법은 [Babel CLI 문서](http://babeljs.io/docs/usage/cli/)를 읽어보세요.
|
||||
|
||||
```javascript{2}
|
||||
ReactDOM.render(
|
||||
@@ -126,7 +132,7 @@ ReactDOM.render(
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="build/react-dom.js"></script>
|
||||
<!-- No need for Babel! -->
|
||||
<!-- Babel은 이제 불필요합니다! -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -68,6 +68,73 @@ factoryFunction createFactory(
|
||||
주어진 타입의 ReactElement를 만들어주는 함수를 리턴합니다. `React.createElement`와 마찬가지로 `type` 인자는 HTML 태그명 문자열 (예: 'div', 'span' 등) 또는 `ReactClass`입니다.
|
||||
|
||||
|
||||
### React.isValidElement
|
||||
|
||||
```javascript
|
||||
boolean isValidElement(* object)
|
||||
```
|
||||
|
||||
주어진 객체가 ReactElement인지 확인합니다.
|
||||
|
||||
|
||||
### React.DOM
|
||||
|
||||
`React.DOM`은 DOM 컴포넌트에 대해 `React.createElement`의 편의 래퍼(wrapper)를 제공합니다. JSX를 사용하지 않는 경우에만 사용하십시오. 예를 들어, `React.DOM.div(null, 'Hello World!')`와 같이 사용할 수 있습니다.
|
||||
|
||||
|
||||
### React.PropTypes
|
||||
|
||||
`React.PropTypes`는 컴포넌트에 넘어오는 props가 올바른지 검사할 수 있는 컴포넌트의 `propTypes` 객체에 들어가는 타입을 가집니다. `propTypes`에 대한 자세한 정보는 [재사용 가능한 컴포넌트](/react/docs/reusable-components-ko-KR.html)를 참고하세요.
|
||||
|
||||
|
||||
### React.Children
|
||||
|
||||
`React.Children`은 불투명한 자료 구조인 `this.props.children`를 다룰 수 있는 유틸리티를 제공합니다.
|
||||
|
||||
#### React.Children.map
|
||||
|
||||
```javascript
|
||||
array React.Children.map(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
`children`의 바로 밑에 있는 모든 자식에 `fn`을 호출합니다. 이 때 `this`는 `thisArg`로 설정됩니다. `children`이 중첩된 객체나 배열일 경우 그 안의 값을 순회합니다. 따라서 `fn`에 컨테이너 객체가 넘어가는 일은 일어나지 않습니다. `children`이 `null`이거나 `undefined`면 배열 대신 `null` 또는 `undefined`를 리턴합니다.
|
||||
|
||||
#### React.Children.forEach
|
||||
|
||||
```javascript
|
||||
React.Children.forEach(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
`React.Children.map()`과 비슷하지만 배열을 리턴하지 않습니다.
|
||||
|
||||
#### React.Children.count
|
||||
|
||||
```javascript
|
||||
number React.Children.count(object children)
|
||||
```
|
||||
|
||||
`children`에 들어있는 컴포넌트의 총 갯수를 리턴합니다. 이 갯수는 `map`이나 `forEach`에 넘긴 콜백이 호출되는 횟수와 동일합니다.
|
||||
|
||||
#### React.Children.only
|
||||
|
||||
```javascript
|
||||
object React.Children.only(object children)
|
||||
```
|
||||
|
||||
`children`에 단 하나의 자식이 있을 때 그 자식을 리턴합니다. 그 밖의 경우에는 예외를 발생시킵니다.
|
||||
|
||||
#### React.Children.toArray
|
||||
|
||||
```javascript
|
||||
array React.Children.toArray(object children)
|
||||
```
|
||||
|
||||
불투명한 자료구조인 `children`를 개별 자식마다 키를 할당해 평면 배열로 리턴합니다. 이는 render 메소드 내에서 자식의 컬렉션을 조작할 때, 특히 `this.props.children`을 넘기기 전에 재정렬하거나 재단할 때 유용합니다.
|
||||
|
||||
## ReactDOM
|
||||
|
||||
`react-dom` 패키지는 앱의 최상위 레벨에서 사용될 DOM 고유의 메소드를 제공하며, 원한다면 리액트 외부모델을 위한 출구로 사용될 수 있습니다. 대부분의 컴포넌트는 이 모듈을 사용할 필요가 없습니다.
|
||||
|
||||
### ReactDOM.render
|
||||
|
||||
```javascript
|
||||
@@ -78,7 +145,7 @@ ReactComponent render(
|
||||
)
|
||||
```
|
||||
|
||||
주어진 ReactElement를 `container` 인자에 넘어온 DOM 안에 렌더링하고 컴포넌트의 레퍼런스를 리턴합니다.
|
||||
주어진 ReactElement를 `container` 인자에 넘어온 DOM 안에 렌더링하고 컴포넌트의 [레퍼런스](/react/docs/more-about-refs-ko-KR.html)를 컴포넌트에 리턴합니다. [상태가 없는 컴포넌트](/react/docs/reusable-components-ko-KR.html#stateless-functions)에서는 `null`을 리턴합니다.
|
||||
|
||||
어떤 ReactElement가 이미 `container`에 렌더링 된 적이 있다면, 그것을 업데이트한 뒤 React 컴포넌트의 최신 상태를 반영하기 위해 꼭 필요한 만큼만 DOM을 변경합니다.
|
||||
|
||||
@@ -100,7 +167,26 @@ boolean unmountComponentAtNode(DOMElement container)
|
||||
DOM에 마운트된 React 컴포넌트를 제거하고 이벤트 핸들러 및 state를 정리합니다. 컨테이너에 마운트된 컴포넌트가 없는 경우에는 호출해도 아무 동작을 하지 않습니다. 컴포넌트가 마운트 해제된 경우 `true`를, 마운트 해제할 컴포넌트가 없으면 `false`를 리턴합니다.
|
||||
|
||||
|
||||
### ReactDOM.renderToString
|
||||
### ReactDOM.findDOMNode
|
||||
|
||||
```javascript
|
||||
DOMElement findDOMNode(ReactComponent component)
|
||||
```
|
||||
이 컴포넌트가 DOM에 마운트된 경우 해당하는 네이티브 브라우저 DOM 엘리먼트를 리턴합니다. 이 메소드는 폼 필드의 값이나 DOM의 크기/위치 등 DOM에서 정보를 읽을 때 유용합니다. **대부분의 경우, DOM 노드에 ref를 쓸 수 있으며 `findDOMNode`를 사욯할 필요는 없습니다.** `render`가 `null`이나 `false`를 리턴할 때 `findDOMNode()`는 `null`을 리턴합니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> `findDOMNode()`는 기본 DOM 노드에 접근하기 위한 출구입니다. 컴포넌트 추상화를 파괴하기 때문에 대부분의 경우 이것의 사용은 권장되지 않습니다.
|
||||
>
|
||||
> `findDOMNode()`는 마운트된 컴포넌트에서만 작동합니다. 이는 컴포넌트가 DOM에 위치해야 함을 뜻합니다. 만약 아직 생성되기전의 컴포넌트에서 `render()`에서 `findDOMNode()`를 호출하는 등 컴포넌트가 마운트 되기 이전에 이를 호출한다면, 예외가 던져질 것입니다.
|
||||
>
|
||||
> `findDOMNode()`는 상태가없는 컴포넌트에서 쓸 수 없습니다.
|
||||
|
||||
## ReactDOMServer
|
||||
|
||||
`react-dom/server` 패키지는 서버단에서 컴포넌트를 렌더할 수 있도록 해 줍니다.
|
||||
|
||||
### ReactDOMServer.renderToString
|
||||
|
||||
```javascript
|
||||
string renderToString(ReactElement element)
|
||||
@@ -111,73 +197,10 @@ string renderToString(ReactElement element)
|
||||
또한 이 메소드로 서버에서 렌더링한 마크업을 포함한 노드에 `ReactDOM.render()`를 호출하면, React는 마크업을 보존하고 이벤트 핸들러만 붙이므로 최초 로딩을 매우 빠르게 느껴지게 할 수 있습니다.
|
||||
|
||||
|
||||
### ReactDOM.renderToStaticMarkup
|
||||
### ReactDOMServer.renderToStaticMarkup
|
||||
|
||||
```javascript
|
||||
string renderToStaticMarkup(ReactElement element)
|
||||
```
|
||||
|
||||
`renderToString`와 비슷하지만 `data-react-id`처럼 React에서 내부적으로 사용하는 추가적인 DOM 어트리뷰트를 만들지 않습니다. 추가적인 어트리뷰트를 제거하면 생성되는 마크업의 용량을 줄일 수 있기 때문에 React를 단순한 정적 페이지 생성기로 사용할 때 유용합니다.
|
||||
|
||||
|
||||
### ReactDOM.isValidElement
|
||||
|
||||
```javascript
|
||||
boolean isValidElement(* object)
|
||||
```
|
||||
|
||||
주어진 객체가 ReactElement인지 확인합니다.
|
||||
|
||||
### ReactDOM.findDOMNode
|
||||
|
||||
```javascript
|
||||
DOMElement findDOMNode(ReactComponent component)
|
||||
```
|
||||
이 컴포넌트가 DOM에 마운트된 경우 해당하는 네이티브 브라우저 DOM 엘리먼트를 리턴합니다. 이 메소드는 폼 필드의 값이나 DOM의 크기/위치 등 DOM에서 정보를 읽을 때 유용합니다. `render`가 `null`이나 `false`를 리턴할 때 `findDOMNode()`는 `null`을 리턴합니다.
|
||||
|
||||
|
||||
### React.DOM
|
||||
|
||||
`React.DOM`은 DOM 컴포넌트에 대해 `React.createElement`의 편의 래퍼(wrapper)를 제공합니다. JSX를 사용하지 않는 경우에만 사용하십시오. 예를 들어, `React.DOM.div(null, 'Hello World!')`와 같이 사용할 수 있습니다.
|
||||
|
||||
|
||||
### React.PropTypes
|
||||
|
||||
`React.PropTypes`는 컴포넌트에 넘어오는 props가 올바른지 검사할 수 있는 컴포넌트의 `propTypes` 객체에 들어가는 타입을 가집니다. `propTypes`에 대한 자세한 정보는 [재사용 가능한 컴포넌트](/react/docs/reusable-components-ko-KR.html)를 참고하세요.
|
||||
|
||||
|
||||
### React.Children
|
||||
|
||||
`React.Children`은 불투명한 자료 구조인 `this.props.children`를 다룰 수 있는 유틸리티를 제공합니다.
|
||||
|
||||
#### React.Children.map
|
||||
|
||||
```javascript
|
||||
object React.Children.map(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
`children`의 바로 밑에 있는 모든 자식에 `fn`을 호출합니다. 이 때 `this`는 `thisArg`로 설정됩니다. `children`이 중첩된 객체나 배열일 경우 그 안의 값을 순회합니다. 따라서 `fn`에 컨테이너 객체가 넘어가는 일은 일어나지 않습니다. `children`이 `null`이거나 `undefined`면 빈 객체 대신 `null` 또는 `undefined`를 리턴합니다.
|
||||
|
||||
#### React.Children.forEach
|
||||
|
||||
```javascript
|
||||
React.Children.forEach(object children, function fn [, object thisArg])
|
||||
```
|
||||
|
||||
`React.Children.map()`과 비슷하지만 객체를 리턴하지 않습니다.
|
||||
|
||||
#### React.Children.count
|
||||
|
||||
```javascript
|
||||
number React.Children.count(object children)
|
||||
```
|
||||
|
||||
`children`에 들어있는 컴포넌트의 총 갯수를 리턴합니다. 이 갯수는 `map`이나 `forEach`에 넘긴 콜백이 호출되는 횟수와 동일합니다.
|
||||
|
||||
#### React.Children.only
|
||||
|
||||
```javascript
|
||||
object React.Children.only(object children)
|
||||
```
|
||||
|
||||
`children`에 단 하나의 자식이 있을 때 그 자식을 리턴합니다. 그 밖의 경우에는 예외를 발생시킵니다.
|
||||
|
||||
@@ -14,14 +14,17 @@ React 컴포넌트의 인스턴스는 React가 렌더링 시에 내부적으로
|
||||
### setState
|
||||
|
||||
```javascript
|
||||
void setState(function|object nextState[, function callback])
|
||||
void setState(
|
||||
function|object nextState,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
`nextState`를 현재 state에 합칩니다. 이벤트 핸들러와 서버 요청 콜백에서 UI 업데이트를 발생시키기 위해 이 메소드를 주로 사용합니다.
|
||||
nextState를 현재 state에 얕게(shallow) 병합합니다. 이벤트 핸들러와 서버 요청 콜백에서 UI 업데이트를 발생시키기 위해 이 메소드를 주로 사용합니다.
|
||||
|
||||
첫번째 인자는 업데이트를 위한 키를 0개 이상 가진 객체이거나 업데이트를 위한 키들을 포함한 객체를 반환하는 함수(의 state나 props)일 수 있습니다.
|
||||
|
||||
객체를 사용하는 간단한 예제입니다...
|
||||
객체를 사용하는 간단한 예제입니다:
|
||||
|
||||
```javascript
|
||||
setState({mykey: '새로운 값'});
|
||||
@@ -51,7 +54,10 @@ setState(function(previousState, currentProps) {
|
||||
### replaceState
|
||||
|
||||
```javascript
|
||||
void replaceState(object nextState[, function callback])
|
||||
void replaceState(
|
||||
object nextState,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
`setState()`와 비슷하지만 기존에 존재하는 state 중 nextState에 없는 키는 모두 삭제됩니다.
|
||||
@@ -64,7 +70,9 @@ void replaceState(object nextState[, function callback])
|
||||
### forceUpdate
|
||||
|
||||
```javascript
|
||||
void forceUpdate([function callback])
|
||||
void forceUpdate(
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
기본적으로, 컴포넌트의 state나 props가 변경되면, 컴포넌트는 다시 렌더됩니다. 하지만 이런 변경이 묵시적이거나(예를들어 객체의 변경 없이 깊이 있는 데이터만 변경된 경우) `render()` 함수가 다른 값에 의존하는 경우, `forceUpdate()`를 호출해 React에게 `render()`를 다시 실행할 필요가 있다고 알릴 수 있습니다.
|
||||
@@ -95,7 +103,7 @@ DOMElement getDOMNode()
|
||||
boolean isMounted()
|
||||
```
|
||||
|
||||
`isMounted()`는 컴포넌트가 DOM에 렌더링되었으면 true를, 아니면 false를 리턴합니다. 비동기적으로 `setState()`나 `forceUpdate()`를 호출할 때 이 메소드를 사용하여 오류를 방지할 수 있습니다.
|
||||
`isMounted()`는 컴포넌트가 DOM에 렌더링되었으면 `true`를, 아니면 `false`를 리턴합니다. 비동기적으로 `setState()`나 `forceUpdate()`를 호출할 때 이 메소드를 사용하여 오류를 방지할 수 있습니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
@@ -105,7 +113,10 @@ boolean isMounted()
|
||||
### setProps
|
||||
|
||||
```javascript
|
||||
void setProps(object nextProps[, function callback])
|
||||
void setProps(
|
||||
object nextProps,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
외부 JavaScript 애플리케이션과 연동하는 경우 `ReactDOM.render()`로 렌더링된 React 컴포넌트에 변경을 알리고 싶을 때가 있습니다.
|
||||
@@ -124,7 +135,10 @@ void setProps(object nextProps[, function callback])
|
||||
### replaceProps
|
||||
|
||||
```javascript
|
||||
void replaceProps(object nextProps[, function callback])
|
||||
void replaceProps(
|
||||
object nextProps,
|
||||
function callback]
|
||||
)
|
||||
```
|
||||
|
||||
`setProps()`와 비슷하지만 두 객체를 합치는 대신 이전에 존재하던 props를 삭제합니다.
|
||||
|
||||
@@ -122,7 +122,7 @@ void componentWillMount()
|
||||
void componentDidMount()
|
||||
```
|
||||
|
||||
최초 렌더링이 일어난 다음 클라이언트에서만 한번 호출됩니다. (서버에서는 호출되지 않습니다.) 이 시점에 컴포넌트는 `ReactDOM.findDOMNode(this)`로 접근 가능한 DOM 표현을 가집니다.
|
||||
최초 렌더링이 일어난 다음 클라이언트에서만 한번 호출됩니다. (서버에서는 호출되지 않습니다.) 이 시점에 자식의 refs들에 접근 할 수 있습니다. (기본 DOM 표현에 접근하는 등). 자식 컴포넌트의 `componentDidMount()` 메소드는 부모 컴포넌트보다 먼저 호출됩니다.
|
||||
|
||||
다른 JavaScript 프레임워크를 연동하거나, `setTimeout`/`setInterval`로 타이머를 설정하고 AJAX 요청을 보내는 등의 작업을 이 메소드에서 합니다.
|
||||
|
||||
@@ -130,7 +130,9 @@ void componentDidMount()
|
||||
### 업데이트 시: componentWillReceiveProps
|
||||
|
||||
```javascript
|
||||
void componentWillReceiveProps(object nextProps)
|
||||
void componentWillReceiveProps(
|
||||
object nextProps
|
||||
)
|
||||
```
|
||||
|
||||
컴포넌트가 새로운 props를 받을 때 호출됩니다. 이 메소드는 최초 렌더링 시에는 호출되지 않습니다.
|
||||
@@ -154,7 +156,9 @@ componentWillReceiveProps: function(nextProps) {
|
||||
### 업데이트 시: shouldComponentUpdate
|
||||
|
||||
```javascript
|
||||
boolean shouldComponentUpdate(object nextProps, object nextState)
|
||||
boolean shouldComponentUpdate(
|
||||
object nextProps, object nextState
|
||||
)
|
||||
```
|
||||
|
||||
새로운 props 또는 state를 받아 렌더링을 하기 전에 호출됩니다. 최초 렌더링 시나 `forceUpdate`를 사용하는 경우에는 호출되지 않습니다.
|
||||
@@ -168,9 +172,9 @@ shouldComponentUpdate: function(nextProps, nextState) {
|
||||
}
|
||||
```
|
||||
|
||||
`shouldComponentUpdate`가 false를 리턴하면, 다음에 state가 바뀌기 전까지 `render()`가 완전히 호출되지 않고 넘어갑니다. (그리고 `componentWillUpdate`와 `componentDidUpdate` 또한 호출되지 않습니다.)
|
||||
`shouldComponentUpdate`가 false를 리턴하면, 다음에 state가 바뀌기 전까지 `render()`가 완전히 호출되지 않고 넘어갑니다. `componentWillUpdate`와 `componentDidUpdate` 또한 호출되지 않습니다.
|
||||
|
||||
기본적으로 `shouldComponentUpdate`는 항상 true를 리턴합니다. `state`가 제자리에서(in place) 바뀐 경우에 발생하는 파악하기 힘든 버그를 막기 위함입니다. 하지만 `state`가 항상 변경 불가능하도록 주의하고 `render()`에서 `props`와 `state`를 읽기만 하면 이전 props 및 state와 바뀌는 값을 비교하는 `shouldComponentUpdate`를 직접 구현할 수 있습니다.
|
||||
기본적으로 `shouldComponentUpdate`는 항상 `true`를 리턴합니다. `state`가 제자리에서(in place) 바뀐 경우에 발생하는 파악하기 힘든 버그를 막기 위함입니다. 하지만 `state`가 항상 변경 불가능하도록 주의하고 `render()`에서 `props`와 `state`를 읽기만 하면 이전 props 및 state와 바뀌는 값을 비교하는 `shouldComponentUpdate`를 직접 구현할 수 있습니다.
|
||||
|
||||
성능에 병목이 있다면, 특히 컴포넌트가 매우 많은 경우 `shouldComponentUpdate`를 사용하여 앱을 빠르게 만들 수 있습니다.
|
||||
|
||||
@@ -178,7 +182,9 @@ shouldComponentUpdate: function(nextProps, nextState) {
|
||||
### 업데이트 시: componentWillUpdate
|
||||
|
||||
```javascript
|
||||
void componentWillUpdate(object nextProps, object nextState)
|
||||
void componentWillUpdate(
|
||||
object nextProps, object nextState
|
||||
)
|
||||
```
|
||||
|
||||
새로운 props나 state를 받았을 때 렌더링 직전에 호출됩니다. 최초 렌더링 시에는 호출되지 않습니다.
|
||||
@@ -193,7 +199,9 @@ void componentWillUpdate(object nextProps, object nextState)
|
||||
### 업데이트 시: componentDidUpdate
|
||||
|
||||
```javascript
|
||||
void componentDidUpdate(object prevProps, object prevState)
|
||||
void componentDidUpdate(
|
||||
object prevProps, object prevState
|
||||
)
|
||||
```
|
||||
|
||||
컴포넌트의 업데이트가 DOM에 반영된 직후에 호출됩니다. 최초 렌더링 시에는 호출되지 않습니다.
|
||||
|
||||
@@ -8,7 +8,7 @@ next: events-ko-KR.html
|
||||
|
||||
## 지원되는 태그
|
||||
|
||||
React는 모든 공통 엘리먼트를 지원하려 합니다. 필요한 엘리먼트가 목록에 없다면, 이슈로 등록해 주세요.
|
||||
React는 모든 공통 엘리먼트를 지원하려 합니다. 필요한 엘리먼트가 목록에 없다면, [이슈로 등록](https://github.com/facebook/react/issues/new)해 주세요.
|
||||
|
||||
### HTML 엘리먼트
|
||||
|
||||
@@ -53,17 +53,17 @@ React는 모든 `data-*`, `aria-*` 어트리뷰트와 밑에 있는 모든 어
|
||||
|
||||
```
|
||||
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
|
||||
async autoComplete autoFocus autoPlay cellPadding cellSpacing charSet challenge
|
||||
checked classID className colSpan cols content contentEditable contextMenu controls
|
||||
coords crossOrigin data dateTime defer dir disabled download draggable encType
|
||||
form formAction formEncType formMethod formNoValidate formTarget frameBorder
|
||||
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing charSet
|
||||
challenge checked classID className cols colSpan content contentEditable contextMenu
|
||||
controls coords crossOrigin data dateTime defer dir disabled download draggable
|
||||
encType form formAction formEncType formMethod formNoValidate formTarget frameBorder
|
||||
headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode
|
||||
keyParams keyType label lang list loop low manifest marginHeight marginWidth max
|
||||
maxLength media mediaGroup method min multiple muted name noValidate open
|
||||
maxLength media mediaGroup method min minlength multiple muted name noValidate open
|
||||
optimum pattern placeholder poster preload radioGroup readOnly rel required role
|
||||
rowSpan rows sandbox scope scoped scrolling seamless selected shape size sizes
|
||||
rows rowSpan sandbox scope scoped scrolling seamless selected shape size sizes
|
||||
span spellCheck src srcDoc srcSet start step style summary tabIndex target title
|
||||
type useMap value width wmode
|
||||
type useMap value width wmode wrap
|
||||
```
|
||||
|
||||
덧붙여, 이런 비표준 어트리뷰트도 지원됩니다.
|
||||
@@ -72,15 +72,19 @@ type useMap value width wmode
|
||||
- [오픈 그래프](http://ogp.me/) 메타 태그를 위한 `property`.
|
||||
- [HTML5 마이크로데이터](http://schema.org/docs/gs.html)를 위한 `itemProp itemScope itemType itemRef itemID`.
|
||||
- 인터넷 익스플로어를 위한 `unselectable`.
|
||||
- WebKit/Blink의 `search` 타입 input 필드를 위한 `results autoSave`
|
||||
|
||||
컴포넌트에 직접 HTML 문자열을 넣을 때 사용하는, React 전용 어트리뷰트 `dangerouslySetInnerHTML`([자세한 정보는 여기](/react/docs/special-non-dom-attributes-ko-KR.html))도 있습니다.
|
||||
|
||||
### SVG 어트리뷰트
|
||||
|
||||
```
|
||||
clipPath cx cy d dx dy fill fillOpacity fontFamily fontSize fx fy
|
||||
gradientTransform gradientUnits markerEnd markerMid markerStart offset opacity
|
||||
patternContentUnits patternUnits points preserveAspectRatio r rx ry
|
||||
spreadMethod stopColor stopOpacity stroke strokeDasharray strokeLinecap
|
||||
strokeOpacity strokeWidth textAnchor transform version viewBox x1 x2 x y1 y2 y
|
||||
clipPath cx cy d dx dy fill fillOpacity fontFamily
|
||||
fontSize fx fy gradientTransform gradientUnits markerEnd
|
||||
markerMid markerStart offset opacity patternContentUnits
|
||||
patternUnits points preserveAspectRatio r rx ry spreadMethod
|
||||
stopColor stopOpacity stroke strokeDasharray strokeLinecap
|
||||
strokeOpacity strokeWidth textAnchor transform version
|
||||
viewBox x1 x2 x xlinkActuate xlinkArcrole xlinkHref xlinkRole
|
||||
xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace y1 y2 y
|
||||
```
|
||||
|
||||
@@ -31,8 +31,33 @@ string type
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> v0.12 시점에서, 이벤트 핸들러에서 `false` 를 리턴하는 것은 더 이상 이벤트의 전달(propagation)을 멈추지 않습니다. 대신, `e.stopPropagation()`나 `e.preventDefault()`로 적절히 수동으로 트리거해야 합니다.
|
||||
> v0.14 시점에서, 이벤트 핸들러에서 `false` 를 리턴하는 것은 더 이상 이벤트의 전달(propagation)을 멈추지 않습니다. 대신, `e.stopPropagation()`나 `e.preventDefault()`로 적절히 수동으로 트리거해야 합니다.
|
||||
|
||||
## 이벤트 풀링
|
||||
|
||||
`SyntheticEvent`는 풀링됩니다. 이는 `SyntheticEvent` 객체가 재사용될 것이며 이벤트 콜백이 호출된 후 모든 프로퍼티가 null 값을 갖게 된다는 것을 뜻합니다.
|
||||
이는 성능을 위한 동작입니다.
|
||||
이 때문에, 비동기 방식으로는 이벤트에 접근할 수 없습니다.
|
||||
|
||||
```javascript
|
||||
function onClick(event) {
|
||||
console.log(event); // => null이 된 객체.
|
||||
console.log(event.type); // => "click"
|
||||
var eventType = event.type; // => "click"
|
||||
|
||||
setTimeout(function() {
|
||||
console.log(event.type); // => null
|
||||
console.log(eventType); // => "click"
|
||||
}, 0);
|
||||
|
||||
this.setState({clickEvent: event}); // 작동하지 않습니다. this.state.clickEvent 는 null값들만을 갖고 있습니다.
|
||||
this.setState({eventType: event.type}); // 여전히 이벤트 프로퍼티를 내보낼 수 있습니다.
|
||||
}
|
||||
```
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 만약 비동기 방식으로 이벤트 프로퍼티에 접근하길 원한다면, 이벤트의 `event.persist()`를 호출해야 합니다, 이는 풀로부터 통합적인 이벤트를 제거하고 이벤트에 대한 참조는 사용자의 코드에 의해 유지 될 수 있도록 합니다.
|
||||
|
||||
## 지원되는 이벤트
|
||||
|
||||
@@ -56,6 +81,22 @@ DOMDataTransfer clipboardData
|
||||
```
|
||||
|
||||
|
||||
### Composition Events
|
||||
|
||||
이벤트 이름:
|
||||
|
||||
```
|
||||
onCompositionEnd onCompositionStart onCompositionUpdate
|
||||
```
|
||||
|
||||
프로퍼티:
|
||||
|
||||
```javascript
|
||||
string data
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 키보드 이벤트
|
||||
|
||||
이벤트 이름:
|
||||
@@ -96,6 +137,7 @@ onFocus onBlur
|
||||
DOMEventTarget relatedTarget
|
||||
```
|
||||
|
||||
이 포커스 이벤트는 폼 엘리먼트뿐만 아니라 모든 React DOM 엘리먼트에서 작동합니다.
|
||||
|
||||
<a name="form-events"></a>
|
||||
### 폼 이벤트
|
||||
@@ -114,11 +156,12 @@ onChange 이벤트에 대한 더 자세한 정보는 [폼](/react/docs/forms-ko-
|
||||
이벤트 이름:
|
||||
|
||||
```
|
||||
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
|
||||
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit
|
||||
onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
|
||||
onMouseMove onMouseOut onMouseOver onMouseUp
|
||||
```
|
||||
|
||||
`onMouseEnter`와 `onMouseLeave` 이벤트는 평범하게 일어나는(bubbling) 대신 입력된 컴포넌트에 남겨지도록 컴포넌트에서 전달되고 캡쳐 단계가 없습니다.
|
||||
`onMouseEnter`와 `onMouseLeave` 이벤트는 평범하게 일어나는(bubbling) 대신 입력된 엘리먼트에 남겨지도록 엘리먼트에서 전달되고 캡쳐 단계가 없습니다.
|
||||
|
||||
프로퍼티:
|
||||
|
||||
@@ -140,6 +183,15 @@ boolean shiftKey
|
||||
```
|
||||
|
||||
|
||||
### 셀렉션 이벤트
|
||||
|
||||
이벤트 이름:
|
||||
|
||||
```
|
||||
onSelect
|
||||
```
|
||||
|
||||
|
||||
### 터치 이벤트
|
||||
|
||||
이벤트 이름:
|
||||
@@ -202,3 +254,11 @@ number deltaZ
|
||||
```
|
||||
onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting
|
||||
```
|
||||
|
||||
### 이미지 이벤트
|
||||
|
||||
이벤트 이름:
|
||||
|
||||
```
|
||||
onLoad onError
|
||||
```
|
||||
|
||||
@@ -44,7 +44,7 @@ var root = <ul className="my-list">
|
||||
ReactDOM.render(root, document.getElementById('example'));
|
||||
```
|
||||
|
||||
__팩토리__
|
||||
### 팩토리
|
||||
|
||||
`ReactElement` 팩토리는 그저 특정한 `type` 프로퍼티를 가지는 `ReactElement`를 만들어주는 함수입니다. React에는 팩토리를 만드는 헬퍼가 내장되어 있습니다. 그 함수는 사실상 다음과 같습니다:
|
||||
|
||||
@@ -105,7 +105,7 @@ var MyComponent = React.createClass({
|
||||
var component = new MyComponent(props); // 절대 하지 마세요.
|
||||
```
|
||||
|
||||
테스트 목적이 아니라면 __절대__ 이 생성자를 직접 호출하지 마십시오. React가 알아서 호출해줍니다.
|
||||
테스트 목적이 아니라면 *절대* 이 생성자를 직접 호출하지 마십시오. React가 알아서 호출해줍니다.
|
||||
|
||||
대신 `ReactComponent` 클래스를 `createElement`에 넘겨 `ReactElement`를 받을 수 있습니다.
|
||||
|
||||
@@ -140,13 +140,13 @@ componentA === componentB; // true
|
||||
|
||||
## 형식 타입 정의
|
||||
|
||||
__진입점__
|
||||
### 진입점
|
||||
|
||||
```
|
||||
ReactDOM.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;
|
||||
```
|
||||
|
||||
__노드와 엘리먼트__
|
||||
### 노드와 엘리먼트
|
||||
|
||||
```
|
||||
type ReactNode = ReactElement | ReactFragment | ReactText;
|
||||
@@ -180,7 +180,7 @@ type ReactText = string | number;
|
||||
type ReactEmpty = null | undefined | boolean;
|
||||
```
|
||||
|
||||
__클래스와 컴포넌트__
|
||||
### 클래스와 컴포넌트
|
||||
|
||||
```
|
||||
type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;
|
||||
|
||||
@@ -26,21 +26,21 @@ next: thinking-in-react-ko-KR.html
|
||||
|
||||
### 서버 구동하기
|
||||
|
||||
이 튜토리얼을 시작할 때 필요한 건 아니지만, 나중에 실행 중인 서버에 `POST` 요청을 하는 기능을 추가하게 될 것입니다. 서버를 구성하는 것이 익숙하다면, 본인이 편한 방식대로 서버를 구성해 주세요. 서버사이드에 대한 고민없이 React의 학습 그 자체에 집중하고 싶은 분들을 위해서, 몇 가지 언어로 간단한 서버코드를 작성해 놓았습니다 - JavaScript (Node.js), Python, Ruby, Go, PHP 버전이 있고, GitHub에서 찾아보실 수 있습니다. [소스를 확인](https://github.com/reactjs/react-tutorial/)하거나 [zip 파일을 다운로드](https://github.com/reactjs/react-tutorial/archive/master.zip)하고 시작하세요.
|
||||
이 튜토리얼을 시작하기 위해, 서버를 구동할 필요가 있습니다. 이 서버는 순수하게 우리가 받고 저장할 데이터의 API 엔드포인트로써만 사용합니다. 이를 가능한한 쉽게하기 위해, 필요한 것만 제공하는 간단한 서버를 몇가지 스크립트 언어로 만들었습니다. **시작하는데 필요한 모든 것이 들어있는 [소스](https://github.com/reactjs/react-tutorial/)를 보시거나 [zip 파일](https://github.com/reactjs/react-tutorial/archive/master.zip)을 다운로드 할 수 있습니다.**
|
||||
|
||||
튜토리얼을 시작하려면, `public/index.html`을 열고 바로 시작하세요.
|
||||
단순하게 하기위해, 서버는 `JSON` 파일을 데이터베이스로 사용합니다. 프로덕션에서 사용할 수는 없지만 이렇게 하면 API를 사용할 때 시뮬레이션이 단순해집니다. 서버가 시작되면, API 엔드포인트를 제공하고 필요한 정적 페이지를 서빙합니다.
|
||||
|
||||
### 시작하기
|
||||
|
||||
이 튜토리얼에서는 CDN에 있는 미리 빌드된 JavaScript 파일들을 사용합니다. 선호하는 에디터에서 `public/index.html`을 열어, 아래의 내용을 채우세요:
|
||||
이 튜토리얼에서는 가능한한 간단하게 만들겠습니다. 위에서 언급된 서버 패키지에 우리가 작업할 HTML 파일 포함되어 있습니다. 편한 편집기에서 `public/index.html`를 여세요. 이는 이런 내용이어야 합니다.(아마 조금 다를 수 있습니다만, 여기에 나중에 `<script>` 태그를 추가 할 것입니다.)
|
||||
|
||||
```html
|
||||
<!-- index.html -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
@@ -48,14 +48,16 @@ next: thinking-in-react-ko-KR.html
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
<script type="text/babel" src="scripts/example.js"></script>
|
||||
<script type="text/babel">
|
||||
// 여기에 코드를 작성합니다
|
||||
// 이 튜토리얼을 시작하려면, 그냥 scripts/example.js를 로드하는 스크립트
|
||||
// 태그를 제거하고 여기에 코드를 적으세요.
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
다음 진행을 위해, 위의 스크립트 태그안에 JavaScript 코드를 작성합니다. 각 단계를 추가한 다음 index.html 파일을 브라우저에서 열어서 진행을 확인하세요.
|
||||
다음 진행을 위해, 위의 스크립트 태그안에 JavaScript 코드를 작성합니다. (이 튜토리얼에서는) 진보된 라이브 리로드가 없기 때문에, 수정 사항을 저장한 다음에는 브라우저를 새로고침해서 확인해야 합니다. 서버를 시작한 다음 브라우저에서 `http://localhost:3000`를 열어 따라해 보세요. 아무런 수정도 하지 않았다면, 최초 로드시 우리가 만들 제품의 완성품을 확인할 수 있을 것입니다. 작업할 준비가 되면, 이전의 `<script>` 태그를 삭제하고 진행하세요.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
@@ -126,6 +128,8 @@ JSX의 사용은 선택적이지만 JSX 문법이 일반 JavsScript보다 사용
|
||||
|
||||
`ReactDOM.render()`는 최상위 컴포넌트의 인스턴스를 만들고, 두 번째 인수로 전달받은 DOM 엘리먼트에 마크업을 삽입해 프레임워크를 시작합니다.
|
||||
|
||||
`ReactDOM` 모듈은 DOM 특정 메소드를 노출해, `React`가 코어 툴을 다른 플렛폼(예를 들어, [React Native](http://facebook.github.io/react-native/))에 공유할 수 있게 합니다.
|
||||
|
||||
## 컴포넌트 조합하기
|
||||
|
||||
이제 `CommentList`와 `CommentForm`을 위한 뼈대를 구축해 봅시다. 이전과 마찬가지로 단순히 `<div>` 태그 하나 입니다. 파일에 두 컴포넌트를 추가해, 이미 있는 `CommentBox` 선언을 참고로 `ReactDOM.render`를 호출합시다.
|
||||
@@ -224,8 +228,8 @@ Markdown은 텍스트를 포맷팅하는 간단한 방식입니다. 예를 들
|
||||
```html{9}
|
||||
<!-- index.html -->
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
@@ -258,17 +262,21 @@ var Comment = React.createClass({
|
||||
|
||||
React는 이런 식으로 [XSS 공격](https://en.wikipedia.org/wiki/Cross-site_scripting)을 예방합니다. 우회할 방법이 있긴 하지만 프레임워크는 사용하지 않도록 경고하고 있습니다:
|
||||
|
||||
```javascript{4,10}
|
||||
```javascript{4,14}
|
||||
// tutorial7.js
|
||||
var Comment = React.createClass({
|
||||
render: function() {
|
||||
rawMarkup: function() {
|
||||
var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
|
||||
return { __html: rawMarkup };
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="comment">
|
||||
<h2 className="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
<span dangerouslySetInnerHTML={{"{{"}}__html: rawMarkup}} />
|
||||
<span dangerouslySetInnerHTML={this.rawMarkup()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -344,13 +352,15 @@ var CommentList = React.createClass({
|
||||
```javascript{3}
|
||||
// tutorial11.js
|
||||
ReactDOM.render(
|
||||
<CommentBox url="comments.json" />,
|
||||
<CommentBox url="/api/comments" />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
이 컴포넌트는 이전 것과 다르게, 스스로 다시 렌더링해야 합니다. 컴포넌트는 서버에서 요청이 들어올때까지는 아무 데이터도 가지고 있지 않다가, 특정한 시점에서 새로운 댓글을 렌더할 필요가 있을 것입니다.
|
||||
|
||||
주의: 이 단계에서 코드는 아직 동작하지 않습니다.
|
||||
|
||||
### 반응적 state
|
||||
|
||||
지금까지, 각각의 컴포넌트는 props를 기반으로 한번 렌더되었습니다. `props`는 불변성을 갖습니다: 그것들은 부모에서 전달되어 부모에게 "소유" 되어 있습니다. 컴포넌트에 상호작용을 구현하기 위해서, 가변성을 갖는 **state**를 소개합니다. `this.state`는 컴포넌트에 한정(private)되며 `this.setState()`를 통해 변경할 수 있습니다. state가 업데이트 되면, 컴포넌트는 자신을 스스로 다시 렌더링합니다.
|
||||
@@ -381,20 +391,15 @@ var CommentBox = React.createClass({
|
||||
|
||||
### state 업데이트하기
|
||||
|
||||
컴포넌트의 최초 생성 시에, 서버에서 GET 방식으로 JSON을 넘겨받아 최신의 데이터가 state에 반영되길 원했습니다. 실제 애플리케이션에선 이것이 동적인 엔드포인트이지만, 이 예제에서는 단순히하기 위해 comments의 배열이 담긴 정적 JSON 파일 `public/comments.json`을 사용하겠습니다.
|
||||
컴포넌트의 최초 생성 시에, 서버에서 GET 방식으로 JSON을 넘겨받아 최신의 데이터가 state에 반영되길 원했습니다. jQuery를 사용해 서버에 비동기 요청을 만들어 필요한 데이터를 빨리 가져올 수 있게 하겠습니다. 이런 식입니다.
|
||||
|
||||
```javascript
|
||||
// tutorial13.json
|
||||
```json
|
||||
[
|
||||
{"author": "Pete Hunt", "text": "댓글입니다"},
|
||||
{"author": "Jordan Walke", "text": "*또 다른* 댓글입니다"}
|
||||
]
|
||||
```
|
||||
|
||||
서버에 비동기 요청을 위해 jQuery를 사용합니다.
|
||||
|
||||
주의: 우리의 앱이 AJAX 애플리케이션으로 변화하고 있기 때문에, 이제 파일 시스템의 파일을 참조하는 대신 웹서버를 사용하도록 앱을 개발해야 합니다. [위에서 언급한 바와 같이](#running-a-server), 우리는 튜토리얼의 나머지 부분에 필요한 기능을 제공하는 서버를 몇 가지 준비해 놓았습니다. [GitHub에 올려놓았으니](https://github.com/reactjs/react-tutorial) 확인해 보세요.
|
||||
|
||||
```javascript{6-18}
|
||||
// tutorial13.js
|
||||
var CommentBox = React.createClass({
|
||||
@@ -463,13 +468,13 @@ var CommentBox = React.createClass({
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<CommentBox url="comments.json" pollInterval={2000} />,
|
||||
<CommentBox url="/api/comments" pollInterval={2000} />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
우리가 여기서 한것은 AJAX 호출을 별도의 메소드로 분리하고 컴포넌트가 처음 로드된 시점부터 2초 간격으로 계속 호출되도록 한 것입니다. 브라우저에서 직접 돌려보고 `comments.json`파일을 수정해보세요; 2초 간격으로 변화되는 모습이 보일 것입니다!
|
||||
우리가 여기서 한것은 AJAX 호출을 별도의 메소드로 분리하고 컴포넌트가 처음 로드된 시점부터 2초 간격으로 계속 호출되도록 한 것입니다. 브라우저에서 직접 돌려보고 `comments.json` 파일(서버의 같은 디렉토리에 있습니다)을 수정해보세요. 2초 간격으로 변화되는 모습이 보일 것입니다!
|
||||
|
||||
### 새로운 댓글 추가하기
|
||||
|
||||
@@ -497,14 +502,14 @@ var CommentForm = React.createClass({
|
||||
var CommentForm = React.createClass({
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var author = ReactDOM.findDOMNode(this.refs.author).value.trim();
|
||||
var text = ReactDOM.findDOMNode(this.refs.text).value.trim();
|
||||
var author = this.refs.author.value.trim();
|
||||
var text = this.refs.text.value.trim();
|
||||
if (!text || !author) {
|
||||
return;
|
||||
}
|
||||
// TODO: 서버에 요청을 전송합니다
|
||||
ReactDOM.findDOMNode(this.refs.author).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.text).value = '';
|
||||
this.refs.author.value = '';
|
||||
this.refs.text.value = '';
|
||||
return;
|
||||
},
|
||||
render: function() {
|
||||
@@ -527,7 +532,7 @@ React는 카멜케이스 네이밍 컨벤션으로 컴포넌트에 이벤트 핸
|
||||
|
||||
##### Refs
|
||||
|
||||
우리는 자식 컴포넌트의 이름을 지정하기 위해 `ref` 어트리뷰트를, 컴포넌트를 참조하기 위해 `this.refs`를 사용합니다. 고유한(native) 브라우저 DOM 엘리먼트를 얻기 위해 `ReactDOM.findDOMNode(component)`를 호출할 수 있습니다.
|
||||
자식 컴포넌트의 이름을 지정하기 위해 `ref` 어트리뷰트를, DOM 노드를 참조하기 위해 `this.refs`를 사용합니다.
|
||||
|
||||
##### props으로 콜백 처리하기
|
||||
|
||||
@@ -580,14 +585,14 @@ var CommentBox = React.createClass({
|
||||
var CommentForm = React.createClass({
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var author = ReactDOM.findDOMNode(this.refs.author).value.trim();
|
||||
var text = ReactDOM.findDOMNode(this.refs.text).value.trim();
|
||||
var author = this.refs.author.value.trim();
|
||||
var text = this.refs.text.value.trim();
|
||||
if (!text || !author) {
|
||||
return;
|
||||
}
|
||||
this.props.onCommentSubmit({author: author, text: text});
|
||||
ReactDOM.findDOMNode(this.refs.author).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.text).value = '';
|
||||
this.refs.author.value = '';
|
||||
this.refs.text.value = '';
|
||||
return;
|
||||
},
|
||||
render: function() {
|
||||
|
||||
@@ -110,7 +110,7 @@ By [Tom Occhino](http://tomocchino.com/), [Jordan Walke](https://github.com/jord
|
||||
### Backbone + React + Middleman Screencast
|
||||
<iframe width="650" height="488" src="https://www.youtube-nocookie.com/embed/iul1fWHVU6A" frameborder="0" allowfullscreen></iframe>
|
||||
|
||||
Backbone은 React로 REST API를 제공하기 위한 아주 좋은 방법입니다. 이 화면중개는 [Backbone-React-Component](https://github.com/magalhas/backbone-react-component)을 이용해서 어떻게 이 두가지를 병합하는지 보여줍니다. Middleman은 이 예제에서 사용되는 프레임워크이지만, 쉽게 다른 프레임워크로 대체하실 수 있습니다. 지원되는 템플릿은 [이곳](https://github.com/jbhatab/middleman-backbone-react-template)에서 찾으실 수 있습니다. -- [열린 마음의 혁명들](http://www.openmindedinnovations.com/)
|
||||
Backbone은 React로 REST API를 제공하기 위한 아주 좋은 방법입니다. 이 화면중개는 [Backbone-React-Component](https://github.com/magalhas/backbone-react-component)을 이용해서 어떻게 이 두가지를 연동하는지 보여줍니다. Middleman은 이 예제에서 사용되는 프레임워크이지만, 쉽게 다른 프레임워크로 대체하실 수 있습니다. 지원되는 템플릿은 [이곳](https://github.com/jbhatab/middleman-backbone-react-template)에서 찾으실 수 있습니다. -- [열린 마음의 혁명들](http://www.openmindedinnovations.com/)
|
||||
|
||||
* * *
|
||||
|
||||
|
||||
@@ -78,4 +78,4 @@ return (
|
||||
>
|
||||
> 위의 예제에 있는 ES6 [화살표 함수](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)는 `this`의 값을 구문적으로 바인드하기위해 사용되었습니다.
|
||||
|
||||
[JSX 컴파일러](/react/jsx-compiler.html)로 지금 바로 사용해보세요.
|
||||
[Babel REPL](https://babeljs.io/repl/)로 지금 바로 사용해보세요.
|
||||
|
||||
@@ -26,7 +26,7 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
하지만 자식이 하나만 있는 경우, `this.props.children`는 _배열 래퍼(wrapper)없이_ 싱글 자식 컴포넌트가 됩니다. 이렇게 함으로써 배열 할당을 줄일 수 있습니다.
|
||||
하지만 자식이 하나만 있는 경우, `this.props.children`는 _배열 래퍼(wrapper)없이_ 싱글 자식 컴포넌트가 됩니다. 이렇게 함으로써 배열 할당을 줄일 수 있습니다.
|
||||
|
||||
```js
|
||||
var GenericWrapper = React.createClass({
|
||||
|
||||
@@ -4,7 +4,7 @@ title: 컴포넌트 함수 드러내기
|
||||
layout: tips
|
||||
permalink: expose-component-functions-ko-KR.html
|
||||
prev: communicate-between-components-ko-KR.html
|
||||
next: references-to-components-ko-KR.html
|
||||
next: children-undefined-ko-KR.html
|
||||
---
|
||||
|
||||
[컴포넌트간의 통신](/react/tips/communicate-between-components-ko-KR.html)을 위한 (일반적이지 않은) 또다른 방법이 있습니다: 단순히 부모의 호출을 위해 자식 컴포넌트의 메소드를 노출하는 겁니다.
|
||||
|
||||
@@ -7,22 +7,4 @@ prev: expose-component-functions-ko-KR.html
|
||||
next: children-undefined-ko-KR.html
|
||||
---
|
||||
|
||||
애플리케이션의 일부에서만 React 컴포넌트를 사용중이거나 코드를 React로 전환하고 있다면, 컴포넌트의 참조를 보존할 필요가 있을 것입니다. `ReactDOM.render`는 마운트된 컴포넌트의 참조를 반환합니다:
|
||||
|
||||
```js
|
||||
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
|
||||
```
|
||||
|
||||
명심하세요, JSX는 컴포넌트 인스턴스를 반환하지 않습니다! 단지 마운트된 컴포넌트가 어떻게 보일지 알려주는 간단한 서술인 **ReactElement**일 뿐입니다.
|
||||
|
||||
```js
|
||||
var myComponentElement = <MyComponent />; // ReactElement일 뿐입니다.
|
||||
|
||||
// 코드들이 여기 위치하게 됩니다...
|
||||
|
||||
var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
|
||||
```
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 이는 최상위 레벨에서만 사용되어야 합니다. 컴포넌트의 내부에서는 `prop`과 `state`가 자식컴포넌트와의 통신을 제어하며, [refs](/react/docs/more-about-refs-ko-KR.html)를 통해서만 컴포넌트를 참조할 수 있습니다.
|
||||
이 페이지는 이동되었습니다. [refs](/react/docs/more-about-refs-ko-KR.html)
|
||||
|
||||
@@ -3,7 +3,7 @@ id: children-undefined-ko-KR
|
||||
title: 정의되지 않은 this.props.children
|
||||
layout: tips
|
||||
permalink: children-undefined-ko-KR.html
|
||||
prev: references-to-components-ko-KR.html
|
||||
prev: expose-component-functions-ko-KR.html
|
||||
next: use-react-with-other-libraries-ko-KR.html
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user