Reactの公式チュートリアルで学んだことメモ（JSX、Reactエレメント、Reactコンポーネント）

こちらの内容のさらっとしたまとめです。
- [JSX](https://reactjs.org/docs/introducing-jsx.html)
- [Rendering Elements](https://reactjs.org/docs/rendering-elements.html)
- [Components and Props](https://reactjs.org/docs/components-and-props.html)

## JSX
JSの拡張文法の一種で、Reactで使うことが推奨されている。
```javascript
const element = <h1>Hello, world!</h1>;
```
`{}`の中にJSの構文を入れることができる。
```javascript
function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);
```
[CodePen](https://codepen.io/gaearon/pen/PGEjdG?editors=1010)

HTMLの属性にJSを入れる場合は`""`をつけないように注意。
```javascript
const element = <img src={user.avatarUrl}></img>;
```
また属性のラベルはキャメルケースにするように注意。(例: `className`、`tabIndex`)

ネストされたDOMを定義する場合は`()`で括る。
```javascript
const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);
```

クロスサイトスクリプティング対策として、JSXで埋め込まれた値はReact DOMがレンダリングする前にエスケープするので安心。
```javascript
// titleに危険な値が入っていてもエスケープされる.
const element = <h1>{title}</h1>;
```

## Reactエレメントとレンダリング

`Babel`によってJSXが変換されてできたオブジェクトを**Reactエレメント**という。
```javascript
// これが
const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

// こうなって
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

// こうなる
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};
```

Reactによって操作する範囲をルートDOMノードと呼び、`root`というIDが付く。通常Reactのみのアプリケーションでは1個のルートDOMノードが存在する。この中身を`ReactDOM.render()`で操作する。`ReactDOM.render()`も通常のReactアプリケーションでは1回だけ呼び出される。

```javascript
// ルートDOMノード
<div id="root">
    <!-- This element's contents will be replaced with your component. -->
</div>
```
```javascript
//ルートDOMノードの内容を書き換える
ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);
```

[CodePen](https://codepen.io/gaearon/pen/edyBaE?editors=1010)

## Reactコンポーネント
Reactエレメントを返す関数のことを**Reactコンポーネント**という。
```javascript
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
```
ES6のクラスを使った書き方
```javascript
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
```
JSXの中にユーザーが定義したタグがあればそのタグと同じ名前のReactコンポーネントが呼び出される。この場合`props`の中身はJSXのタグ内のプロパティになる。
```javascript
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);
```
[CodePen](https://reactjs.org/docs/components-and-props.html)

一つのコンポーネントから他のコンポーネントを呼び出すこともできる。
```javascript
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
```
[CodePen](https://reactjs.org/docs/components-and-props.html)

UIの中に何度も使うパーツ（ボタン等）や複雑なパーツ（コメント、フィード等）があれば一つのコンポーネントとして切り出すのがベストプラクティス。

[CodePen](https://codepen.io/gaearon/pen/MjQWQO?editors=1010)

コンポーネントは`props`の値を書き換えてはいけないので注意。
↓OK
```javascript
function sum(a, b) {
  return a + b;
}
```
↓NG
```javascript
function withdraw(account, amount) {
  account.total -= amount;
}
```