Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translate render-props #73

Merged
merged 16 commits into from
Apr 17, 2019
102 changes: 51 additions & 51 deletions content/docs/render-props.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ title: Render Props
permalink: docs/render-props.html
---

The term ["render prop"](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce) refers to a technique for sharing code between React components using a prop whose value is a function.
["render prop"](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce)란, React 컴포넌트 간에 코드를 공유하기 위해 함수 props를 이용하는 간단한 테크닉입니다.

A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.
render props 패턴으로 구현된 컴포넌트는 자체적으로 렌더링 로직을 구현하는 대신, react 엘리먼트 요소를 반환하고 이를 호출하는 함수를 사용합니다.

```jsx
<DataProvider render={data => (
<h1>Hello {data.target}</h1>
)}/>
```

Libraries that use render props include [React Router](https://reacttraining.com/react-router/web/api/Route/render-func) and [Downshift](https://github.com/paypal/downshift).
render props를 사용하는 라이브러리는 [React Router](https://reacttraining.com/react-router/web/api/Route/Route-render-methods)와 [Downshift](https://github.com/paypal/downshift)가 있습니다.

In this document, we’ll discuss why render props are useful, and how to write your own.
이 문서에서는 왜 render props가 왜 유용하고, 어떻게 여러분의 프로젝트에 적용할 수 있을지에 관해 이야기 하겠습니다.
simsim0709 marked this conversation as resolved.
Show resolved Hide resolved

## Use Render Props for Cross-Cutting Concerns {#use-render-props-for-cross-cutting-concerns}
## 횡단 관심사(Cross-Cutting Concerns)를 위한 render props 사용법 {#use-render-props-for-cross-cutting-concerns}

Components are the primary unit of code reuse in React, but it's not always obvious how to share the state or behavior that one component encapsulates to other components that need that same state.
컴포넌트는 React에서 코드의 재사용성을 위해 사용하는 주요 단위입니다. 하지만 컴포넌트에서 캡슐화된 상태나 동작을 같은 상태를 가진 다른 컴포넌트와 공유하는 방법이 항상 명확하지는 않습니다.

For example, the following component tracks the mouse position in a web app:
예를 들면, 아래 컨포넌트는 웹 애플리케이션에서 마우스 위치를 추적하는 로직을 가지고 있습니다:
hg-pyun marked this conversation as resolved.
Show resolved Hide resolved

```js
class MouseTracker extends React.Component {
Expand Down Expand Up @@ -50,14 +50,14 @@ class MouseTracker extends React.Component {
}
```

As the cursor moves around the screen, the component displays its (x, y) coordinates in a `<p>`.
스크린 주위로 마우스 커서를 움직이면, 컴포넌트가 마우스의 (x, y) 좌표를 `<p>`에 나타냅니다.

Now the question is: How can we reuse this behavior in another component? In other words, if another component needs to know about the cursor position, can we encapsulate that behavior so that we can easily share it with that component?
여기서 질문입니다: 다른 컴포넌트에서 이 행위를 재사용하려면 어떻게 해야 할까요? 즉, 다른 컴포넌에서 커서(cursor) 위치에 대해 알아야 할 경우, 쉽게 공유할 수 있도록 캡슐화할 수 있습니까?
hg-pyun marked this conversation as resolved.
Show resolved Hide resolved

Since components are the basic unit of code reuse in React, let's try refactoring the code a bit to use a `<Mouse>` component that encapsulates the behavior we need to reuse elsewhere.
React에서 컴포넌트는 코드 재사용의 기본 단위이므로, 우리가 필요로 하는 마우스 커서 트래킹 행위를 `<Mouse>` 컴포넌트로 캡슐화하여 어디서든 사용할 수 있게 리팩토링해 보겠습니다.

```js
// The <Mouse> component encapsulates the behavior we need...
// <Mouse> 컴포넌트는 우리가 원하는 행위를 캡슐화 합니다...
class Mouse extends React.Component {
constructor(props) {
super(props);
Expand All @@ -76,7 +76,7 @@ class Mouse extends React.Component {
return (
<div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

{/* ...but how do we render something other than a <p>? */}
{/* ...하지만 <p>가 아닌 다른것을 렌더링하려면 어떻게 해야 할까요? */}
<p>The current mouse position is ({this.state.x}, {this.state.y})</p>
</div>
);
Expand All @@ -95,11 +95,11 @@ class MouseTracker extends React.Component {
}
```

Now the `<Mouse>` component encapsulates all behavior associated with listening for `mousemove` events and storing the (x, y) position of the cursor, but it's not yet truly reusable.
이제 `<Mouse>` 컨포넌트는 마우스 움직임 이벤트를 감지하고, 마우스 커서의 `(x, y)`위치를 저장하는 행위를 캡슐화했습니다. 그러나 아직 완벽하게 재사용할 수 있는 건 아닙니다.

For example, let's say we have a `<Cat>` component that renders the image of a cat chasing the mouse around the screen. We might use a `<Cat mouse={{ x, y }}>` prop to tell the component the coordinates of the mouse so it knows where to position the image on the screen.
예를 들어, 마우스 주위에 고양이 그림을 보여주는 `<Cat>` 컴포넌트를 생각해 보겠습니다. 우리는 `<Cat mouse={{x, y}}>` prop을 통해 Cat 컴포넌트에 마우스 좌표를 전달해주고 화면에 어떤 위치에 이미지를 보여줄지 알려 주고자 합니다.

As a first pass, you might try rendering the `<Cat>` *inside `<Mouse>`'s `render` method*, like this:
첫 번째 방법으로는, 다음과 같이 `<Mouse>` 컴포넌트의 *render 메서드안에* `<Cat>` 컨포넌트를 넣어 렌더링하는 방법이 있습니다:

```js
class Cat extends React.Component {
Expand Down Expand Up @@ -127,13 +127,13 @@ class MouseWithCat extends React.Component {

render() {
return (
<div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

<div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
{/*
We could just swap out the <p> for a <Cat> here ... but then
we would need to create a separate <MouseWithSomethingElse>
component every time we need to use it, so <MouseWithCat>
isn't really reusable yet.
여기서 <p><Cat>으로 바꿀 수 있습니다. ... 그러나 이 경우
Mouse 컴포넌트를 사용할 때 마다 뱔도의 <MouseWithSomethingElse>
hg-pyun marked this conversation as resolved.
Show resolved Hide resolved
컴포넌트를 만들어야 합니다, 그러므로 <MouseWithCat>
아직 정말로 재사용이 가능한게 아닙니다.
*/}
<Cat mouse={this.state} />
</div>
Expand All @@ -153,9 +153,9 @@ class MouseTracker extends React.Component {
}
```

This approach will work for our specific use case, but we haven't achieved the objective of truly encapsulating the behavior in a reusable way. Now, every time we want the mouse position for a different use case, we have to create a new component (i.e. essentially another `<MouseWithCat>`) that renders something specifically for that use case.
이러한 접근 방법은 특정 사례에서는 적용할 수 있지만, 우리가 원하는 행위의 캡슐화(마우스 트랙킹)라는 목표는 달성하지 못했습니다. 이제 우리는 다른 사용 예제에서도 언제든지 마우스 위치를 추적할 수 있는 새로운 component(`<MouseWithCat>`과 근본적으로 다른)를 만들어야 합니다.
simsim0709 marked this conversation as resolved.
Show resolved Hide resolved

Here's where the render prop comes in: Instead of hard-coding a `<Cat>` inside a `<Mouse>` component, and effectively changing its rendered output, we can provide `<Mouse>` with a function prop that it uses to dynamically determine what to render–a render prop.
여기에 render prop를 사용할 수 있습니다. `<Mouse>` 컴포넌트 안에 `<Cat>` 컴포넌트를 하드 코딩(hard-coding)해서 결과물을 바꾸는 대신에, `<Mouse>`에게 동적으로 렌더링할 수 있도록 해주는 함수 prop을 제공하는 것입니다. — 이것이 render prop의 개념입니다.

```js
class Cat extends React.Component {
Expand Down Expand Up @@ -184,10 +184,10 @@ class Mouse extends React.Component {
render() {
return (
<div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

{/*
Instead of providing a static representation of what <Mouse> renders,
use the `render` prop to dynamically determine what to render.
<Mouse>가 무엇을 렌더링하는지에 대해 명확히 코드로 표기하는 대신,
`render` prop을 사용하여 무엇을 렌더링할지 동적으로 결정할 수 있습니다.
*/}
{this.props.render(this.state)}
</div>
Expand All @@ -209,17 +209,17 @@ class MouseTracker extends React.Component {
}
```

Now, instead of effectively cloning the `<Mouse>` component and hard-coding something else in its `render` method to solve for a specific use case, we provide a `render` prop that `<Mouse>` can use to dynamically determine what it renders.
이제 <Mouse> 컴포넌트의 행위를 복제하기 위해 하드 코딩할 필요 없이 `render` 함수에 prop으로 전달해줌으로써, `<Mouse>` 컴포넌트는 동적으로 트래킹 기능을 가진 컴포넌트들을 렌더링할 수 있습니다.

More concretely, **a render prop is a function prop that a component uses to know what to render.**
정리하자면, **render prop은 무엇을 렌더링할지 컴포넌트에 알려주는 함수입니다.**

This technique makes the behavior that we need to share extremely portable. To get that behavior, render a `<Mouse>` with a `render` prop that tells it what to render with the current (x, y) of the cursor.
이 테크닉은 행위(마우스 트래킹 같은)를 매우 쉽게 공유할 수 있도록 만들어 줍니다. 해당 행위를 적용하려면, `<Mouse>` 를 그리고 현재 (x, y) 커서 위치에 무엇을 그릴지에 대한 정보를 prop을 통해 넘겨주기만 하면 됩니다.

One interesting thing to note about render props is that you can implement most [higher-order components](/docs/higher-order-components.html) (HOC) using a regular component with a render prop. For example, if you would prefer to have a `withMouse` HOC instead of a `<Mouse>` component, you could easily create one using a regular `<Mouse>` with a render prop:
render props에 대해 한가지 흥미로운 점은 대부분의 [higher-order components](/docs/higher-order-components.html)(HOC)에 render props pattern을 이식할 수 있습니다. 예를 들면, 만약에 <Mouse> 컴포넌트보다 withMouse HOC를 더 선호한다면 render prop을 이용해서 다음과 같이 쉽게 HOC를 만들 수 있습니다.

```js
// If you really want a HOC for some reason, you can easily
// create one using a regular component with a render prop!
// 만약 어떤 이유 때문에 HOC를 만들기 원한다면, 쉽게 구현할 수 있습니다.
// render prop을 이용해서 일반적인 컴포넌트를 만드세요!
function withMouse(Component) {
return class extends React.Component {
render() {
Expand All @@ -233,21 +233,21 @@ function withMouse(Component) {
}
```

So using a render prop makes it possible to use either pattern.
따라서 render props를 사용하면 두 가지 패턴 모두 사용이 가능합니다.

## Using Props Other Than `render` {#using-props-other-than-render}
## `rener` 의외의 Props 사용법 {#using-props-other-than-render}
hg-pyun marked this conversation as resolved.
Show resolved Hide resolved

It's important to remember that just because the pattern is called "render props" you don't *have to use a prop named `render` to use this pattern*. In fact, [*any* prop that is a function that a component uses to know what to render is technically a "render prop"](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce).
여기서 중요하게 기억해야 할 것은, “render props pattern”으로 불리는 이유로 *꼭 prop name으로 `render`를 사용할 필요는 없습니다.* 사실, [*어떤* 함수형 prop이든 render prop이 될 수 있습니다.](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce)

Although the examples above use `render`, we could just as easily use the `children` prop!
위 예제에서는 `render`를 사용했지만, 우리는 `children` prop을 더 쉽게 사용할 수 있습니다.

```js
<Mouse children={mouse => (
<p>The mouse position is {mouse.x}, {mouse.y}</p>
)}/>
```

And remember, the `children` prop doesn't actually need to be named in the list of "attributes" in your JSX element. Instead, you can put it directly *inside* the element!
실제로 JSX element의 “속성”목록에 하위 속성 이름(예를들면 render)을 지정할 필요는 없습니다. 대신에, element *안에* 직접 꽂아넣을 수 있습니다!
simsim0709 marked this conversation as resolved.
Show resolved Hide resolved

```js
<Mouse>
Expand All @@ -257,27 +257,27 @@ And remember, the `children` prop doesn't actually need to be named in the list
</Mouse>
```

You'll see this technique used in the [react-motion](https://github.com/chenglou/react-motion) API.
이 테크닉은 [react-motion](https://github.com/chenglou/react-motion) API에서 실제로 사용된 것을 볼 수 있습니다.

Since this technique is a little unusual, you'll probably want to explicitly state that `children` should be a function in your `propTypes` when designing an API like this.
이 테크닉은 자주 사용되지 않기 때문에, API를 디자인할 때 `children`은 함수 타입을 가지도록 `propTypes`를 지정하는 것이 좋습니다.

```js
Mouse.propTypes = {
children: PropTypes.func.isRequired
};
```

## Caveats {#caveats}
## 주의사항 {#caveats}

### Be careful when using Render Props with React.PureComponent {#be-careful-when-using-render-props-with-reactpurecomponent}
### React.PureComponent에서 render props pattern을 사용할 땐 주의해주세요. {#be-careful-when-using-render-props-with-reactpurecomponent}

Using a render prop can negate the advantage that comes from using [`React.PureComponent`](/docs/react-api.html#reactpurecomponent) if you create the function inside a `render` method. This is because the shallow prop comparison will always return `false` for new props, and each `render` in this case will generate a new value for the render prop.
render props 패턴을 사용하면 [`React.PureComponent`](/docs/react-api.html#reactpurecomponent)를 사용할 때 발생하는 이점이 사라질 수 있습니다. 얕은 prop 비교는 새로운 prop에 대해 항상 `false`를 반환합니다. 이 경우 `render`마다 render prop으로 넘어온 값을 항상 새로 생성합니다.

For example, continuing with our `<Mouse>` component from above, if `Mouse` were to extend `React.PureComponent` instead of `React.Component`, our example would look like this:
위에서 사용했던 `<Mouse>` 컴포넌트를 이용해서 예를 들어보겠습니다. mouse에 `React.Component` 대신에 `React.PureComponent`를 사용하면 다음과 같은 코드가 됩니다.

```js
class Mouse extends React.PureComponent {
// Same implementation as above...
// 위와 같은 구현체...
}

class MouseTracker extends React.Component {
Expand All @@ -287,8 +287,8 @@ class MouseTracker extends React.Component {
<h1>Move the mouse around!</h1>

{/*
This is bad! The value of the `render` prop will
be different on each render.
이것은 좋지 않습니다! `render` prop이 가지고 있는 값은
각각 다른 컴포넌트를 렌더링 할 것입니다.
*/}
<Mouse render={mouse => (
<Cat mouse={mouse} />
Expand All @@ -299,14 +299,14 @@ class MouseTracker extends React.Component {
}
```

In this example, each time `<MouseTracker>` renders, it generates a new function as the value of the `<Mouse render>` prop, thus negating the effect of `<Mouse>` extending `React.PureComponent` in the first place!
이 예제에서 `<MouseTracker>`가 render 될때마다, `<Mouse render>`의 prop으로 넘어가는 함수가 계속 새로 생성됩니다. 따라서 `React.PureComponent`를 상속받은 `<Mouse>` 컴포넌트 효과가 사라지게 됩니다.

To get around this problem, you can sometimes define the prop as an instance method, like so:
이 문제를 해결하기 위해서, 다음과 같이 인스턴스 메서를 사용해서 prop을 정의합니다:
hg-pyun marked this conversation as resolved.
Show resolved Hide resolved

```js
class MouseTracker extends React.Component {
// Defined as an instance method, `this.renderTheCat` always
// refers to *same* function when we use it in render
// `this.renderTheCat`를 항상 생성하는 매서드를 정의합니다.
// 이것은 render를 사용할 때 마다 *같은* 함수를 참조합니다.
renderTheCat(mouse) {
return <Cat mouse={mouse} />;
}
Expand All @@ -322,4 +322,4 @@ class MouseTracker extends React.Component {
}
```

In cases where you cannot define the prop statically (e.g. because you need to close over the component's props and/or state) `<Mouse>` should extend `React.Component` instead.
만약 prop을 정적으로 정의할 수 없는 경우에는 `<Mouse>` 컴포넌트는 `React.Component`를 상속받아야 합니다.