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 #49

Merged
merged 15 commits into from
Feb 6, 2019
69 changes: 39 additions & 30 deletions content/docs/render-props.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
---
id: render-props
title: Render Props
title: レンダープロップ
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.
[「レンダープロップ」](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce)とは、値が関数となる props を持ったコンポーネント間でコードを共有するためのテクニックの1つです。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.
レンダープロップを持つコンポーネントは、自身のレンダーロジックを実装する代わりに、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/Route-render-methods) and [Downshift](https://github.com/paypal/downshift).
レンダープロップを用いたライブラリとしては、[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.
このドキュメントでは、レンダープロップが役立つ理由と、その記述法について解説します。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

## 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 でコードを再利用するための主要な構成用要素ですが、あるコンポーネントがカプセル化した state や振る舞いを、同じ state を必要とする別のコンポーネントに共有する方法については、いつも明らかであるとは限りません。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

For example, the following component tracks the mouse position in a web app:
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

smikitky marked this conversation as resolved.
Show resolved Hide resolved
たとえば、以下のコンポーネントは、ウェブアプリケーション内でのマウスの位置を追跡します。

```js
class MouseTracker extends React.Component {
constructor(props) {
Expand All @@ -50,11 +52,11 @@ 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?
ここで疑問となるのは、この振る舞いを他のコンポーネントで再利用する方法です。つまり、他のコンポーネントもカーソルの位置を知る必要がある時、この振る舞いだけをカプセル化し、そのコンポーネントと簡単に共有することは可能でしょうか?

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>` コンポーネントを使ってみましょう。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

```js
// The <Mouse> component encapsulates the behavior we need...
Expand Down Expand Up @@ -95,11 +97,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>` コンポーネントは、 `mousemove` イベントに応答しカーソルの (x, y) 座標を保持することで構成される全ての振る舞いをカプセル化できましたが、まだ再利用可能と言うには不十分です。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

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 }}>` props を使って、このコンポーネントにマウスの座標を受け渡し、画面上のどこに猫の画像を配置すれば良いかを知らせたいでしょう。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

As a first pass, you might try rendering the `<Cat>` *inside `<Mouse>`'s `render` method*, like this:
手始めに、*`<Mouse>``render` メソッド内* で、以下のように `<Cat>` をレンダーしようとするかもしれません。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

```js
class Cat extends React.Component {
Expand Down Expand Up @@ -153,9 +155,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.
これだけが目的であればで正しく動作しますが、再利用可能な方法でこの振る舞いをカプセル化するという目的はまだ果たせていません。その他のユースケースでもマウス位置を知りたい場合、毎回新しいコンポーネント(つまり、別の `<MouseWithCat>` のようなもの)を作成して、そのユースケース固有のレンダー処理を行う必要があります。
ossan-engineer 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.
ここでレンダープロップの出番となります。`<Mouse>` コンポーネント内でハードコードされた `<Cat>` でレンダーの出力を変更する代わりに、`<Mouse>` コンポーネントに関数型の props を渡して、 何をレンダーすべきかを動的に決定することが可能です。これがレンダープロップの役割です。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

```js
class Cat extends React.Component {
Expand Down Expand Up @@ -209,13 +211,15 @@ 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>` コンポーネントを複製してレンダーメソッド内で何か他のものをハードコードする代わりに、`<Mouse>` が動的にレンダーの内容を決定するためのpropsとしての `render` が提供可能になります。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

smikitky marked this conversation as resolved.
Show resolved Hide resolved
More concretely, **a render prop is a function prop that a component uses to know what to render.**
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

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.
より具体的には、**レンダープロップは関数型 props であり、それによってコンポーネントがレンダリングするものを知ることができます。**
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

このテクニックによって、再利用可能な振る舞いの移植性が極めて高くなります。この振る舞いが必要な時には、現在のカーソルの (x, y) からレンダリングするものを示す `render` props を使って `<Mouse>` をレンダーすれば良いのです。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

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:
レンダープロップの興味深い点として、多くの[高階コンポーネント](/docs/higher-order-components.html) (HOC) がレンダープロップを使った通常のコンポーネントによって実装可能ということが挙げられます。たとえば、`<Mouse>` コンポーネントよりも `withMouse` HOCが好みであれば、レンダープロップを有する `<Mouse>` を使って簡単に作成可能です。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

```js
// If you really want a HOC for some reason, you can easily
Expand All @@ -233,21 +237,21 @@ function withMouse(Component) {
}
```

So using a render prop makes it possible to use either pattern.
つまり、レンダープロップによってどちらのパターンも可能になります。

## Using Props Other Than `render`
## `render` 以外の props を使う

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 を使う必要はない*ということを念頭に置いてください。実際、[コンポーネントがレンダーするものを知るための関数型 props であれば、*その名前が何であれ*、技術的には「レンダープロップ」と呼ぶことができます](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce)
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

Although the examples above use `render`, we could just as easily use the `children` prop!
上記の例では `rendrer` を用いていますが、`children` props を使っても同じくらい簡単です!
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

```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!
さらに、`children` props は実際には JSX 要素の「属性」の一覧内で名前を付ける必要がないことも忘れないでください。代わりに、要素*内部に*直接設定可能です!
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

```js
<Mouse>
Expand All @@ -257,23 +261,28 @@ 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 などで使用されています。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved


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.
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

smikitky marked this conversation as resolved.
Show resolved Hide resolved
このテクニックは若干珍しいため、このようなAPI設計時には、`children` が関数であることを `propTypes` で明示した方が良いでしょう。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

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

## Caveats
## 注意事項

smikitky marked this conversation as resolved.
Show resolved Hide resolved
### Be careful when using Render Props with React.PureComponent
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

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.
### レンダープロップを React.PureComponent で使うときの注意点

レンダープロップを使う際、`render` メソッド内で関数を作成していると、 [`React.PureComponent`](/docs/react-api.html#reactpurecomponent) を使う利点が相殺されます。これは新しい props については、浅い比較が常に `false` を返し、このような `render` は毎回レンダープロップとして新しい値を生成するためです。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

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 {
Expand All @@ -299,9 +308,9 @@ 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>` がレンダーされるたび、`<Mouse render>` propsの値として新しい関数が生成されますので、冒頭で `React.PureComonent` を継承した `<Mouse>` の効果が相殺されます。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

To get around this problem, you can sometimes define the prop as an instance method, like so:
この問題を回避するため、props をインスタンスメソッドとして次のように定義することもできます。
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved

```js
class MouseTracker extends React.Component {
Expand All @@ -322,4 +331,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.
propsを静的に定義できない場合(たとえば、コンポーネントの props state を閉じる必要があるなど)、`<Mouse>` は代わりに `React.Component` を継承すべきです。
smikitky marked this conversation as resolved.
Show resolved Hide resolved
ossan-engineer marked this conversation as resolved.
Show resolved Hide resolved