Reactがちょっといい感じになる書き方メモ

https://reactjs.org/ を見て、気になった書き方・機能をまとめていきます。

## Inline If with Logical && Operator

特定の条件の場合のみ表示する、というシチュエーションはよくあります。

例えば、エラーが存在する場合のみ、エラーメッセージを表示するなど。

普通に書くと、下記のようになる。

```js
class App extends Component {
  render() {
    let errorMessage = "XXX is required."; // or null

    let errorMessageTag = null;
    if (errorMessage) {
      errorMessageTag = <p className="App-intro">error:{errorMessage}</p>
    }

    return (
      <div>
        {errorMessageTag}
      </div>
    );
  }
}
```

https://reactjs.org/docs/conditional-rendering.html#inline-if-with-logical--operator を見ると、下記のように書けるようです。

```js
class App extends Component {
  render() {
    let errorMessage = "XXX is required."; // or null

    return (
      <div>
        {errorMessage &&
          <p className="App-intro">error:{errorMessage}</p>
        }
      </div>
    );
  }
}
```

## Preventing Component from Rendering

ただ、上記のような場合は、別コンポーネントにしたほうが良さそうです。
https://reactjs.org/docs/conditional-rendering.html#preventing-component-from-rendering


```js
function ErrorMessage(props) {
  if (!props.errorMessage) {
    return null;
  }

  return (
    <div>error:{props.errorMessage}</div>
  );
}

class App extends Component {
  render() {
    let errorMessage = "XXX is required."; // or null

    return (
      <div>
        <ErrorMessage errorMessage={errorMessage} />
      </div>
    );
  }
}
```

（`ErrorMessage` はタグ名になるのでUpperCamelCaseになりますが、functionでもあるのでちょっと気持ち悪い。）

## Inline If-Else with Conditional Operator

特定の条件によってAとBの表示を切り替える、というシチュエーションもよくあります。

例えば、「ログインボタン」と「ログアウトボタン」を切り替えたり。

そのまま書くと、下記のようになる。

```js
class App extends Component {
  render() {
    let flag = true;

    let sample = null;
    if (flag) {
      sample = <p className="App-intro">Hoge.</p>;
    } else {
      sample = <p className="App-intro">Fuga.</p>;
    }

    return (
      <div>
        {sample}
      </div>
    );
  }
}
```

https://reactjs.org/docs/conditional-rendering.html#inline-if-else-with-conditional-operator を見ると、もっと手軽に書けそうです。

```js
class App extends Component {
  render() {
    let flag = false;

    return (
      <div>
        {flag ? (
          <p className="App-intro">Hoge.</p>
        ) : (
          <p className="App-intro">Fuga.</p>
        )}
      </div>
    );
  }
}
```

## Specialization

Dialogなどは、外枠が共通で、中身が「タイトルだけ」だったり「メッセージに装飾がついてる」だったり「ボタンが複数」だったりします。
そんなときは、 `children` という特別なpropを使うようです。

https://reactjs.org/docs/composition-vs-inheritance.html#specialization

```js
function Dialog(props) {
  const style = {
    backgroundColor: "#ff0000",
    margin: "10px"
  };
  return <div style={style}>{props.children}</div>;
}

class App extends Component {
  render() {
    return (
      <div>
        <Dialog>メッセージのみ</Dialog>
        <Dialog>
          <span>ボタンもあるイメージ</span>
          <button href="alert('test');">OK</button>
        </Dialog>
      </div>
    );
  }
}
```

## Using Dot Notation for JSX Type

https://reactjs.org/docs/jsx-in-depth.html#using-dot-notation-for-jsx-type
このリンクにあるように、`<MyComponents.DatePicker />`みたいにモジュール化？できます。

プロジェクト内の汎用のコンポーネントを `MyComponents` の中に入れておき、そこから画面ごとのコンポーネントを作成する、とかもいいかもしれません。

## Choosing the Type at Runtime

https://reactjs.org/docs/jsx-in-depth.html#choosing-the-type-at-runtime
動的に表示するタグを決めることも出来ます。

便利そうですが、使い所は思いついていないです。

```js
const Sample1 = () => <div>This is Sample1.</div>;
const Sample2 = () => <div>This is Sample2.</div>;

class App extends Component {
  render() {
    let flag = true; // or false
    const Hoge = flag ? Sample1 : Sample2;
    return (
      <div>
        <Hoge />
      </div>
    );
  }
}
```

## Spread Attributes

`...` を使うと、objectを展開してパラメータにすることができるようです。
例えば、次の2つは同じ結果になります。

```js
function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}
```

それ以外にも、一部（この場合はkind）を消化して、それ以外を子要素に渡すといったこともできそうです。

```js
const Button = props => {
  const { kind, ...other } = props;
  const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
  return <button className={className} {...other} />;
};

const App = () => {
  return (
    <div>
      <Button kind="primary" onClick={() => console.log("clicked!")}>
        Hello World!
      </Button>
    </div>
  );
};
```

ただ、安易にこれを使いすぎると、どのパラメータが必要・有効なのかが分からなくなってしまいそうです。
（そのために、FlowやTypeScriptで型定義をしておいたほうがいいかも？）

## Children in JSX - String Literals

https://reactjs.org/docs/jsx-in-depth.html#string-literals

HTMLとしてのみやすさを重視すると、タグ直後や途中で改行を入れたくなります。
ただ、通常のHTMLでは改行・スペースが反映されてしまい、レイアウトが崩れる場合がありました。

JSXでは、改行やスペースを削除してくれるようです。
そのため、下記は同一のHTMLとしてレンダリングされます。

```js
class App extends Component {
  render() {
    return (
      <div>
        <div>Hello World</div>

        <div>
          Hello World
        </div>
      </div>
    );
  }
}
```

## Refs and the DOM

https://reactjs.org/docs/refs-and-the-dom.html

フォーカスや文字の選択などの、DOMの直接操作が必要な事態は出てきます。

そのために、idを振って、`document.getElementById('foo')`としてDOMを取得することは出来ます。
Reactでは、同様のことを`ref`を使って実現できます。

```js
class App extends Component {
  constructor(props) {
    super(props);
    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    this.textInput.focus();
  }

  render() {
    return (
      <div>
        <input
          type="text"
          ref={input => {
            this.textInput = input;
          }}
        />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}
```

## Fragments

https://reactjs.org/docs/fragments.html

Reactのcomponentは、特定のタグの下に置く必要があります。
なので、下記のような書き方は出来ません。

```js
const Sample0 = () => (
  This is <span style={{ color: "#f00" }}>Sample1</span>.
);
```

ただ、`<div>`タグが必要ない場合もあります。`<React.Fragment>`を使えば、実現できるようです。

```js
const Sample1 = () => (
  <React.Fragment>
    This is <span style={{ color: "#f00" }}>Sample1</span>.
  </React.Fragment>
);

const Sample2 = () => (
  <div>
    This is <span style={{ color: "#f00" }}>Sample2</span>.
  </div>
);

class App extends Component {
  render() {
    return (
      <div>
        <Sample1 />
        <Sample2 />
      </div>
    );
  }
}
```

レンダリング結果は下記のようになります。

```html
<div>
  This is <span style="color: rgb(255, 0, 0);">Sample1</span>.
  <div>This is <span style="color: rgb(255, 0, 0);">Sample2</span>.</div>
</div>
```

## まとめ

こんな感じで、いろいろな書き方があるので、それらを駆使して読みやすいコードを心がけていきたいですね。