React の公式ドキュメントを読んで脱初心者したい！

最近 [React の公式ドキュメント](https://ja.legacy.reactjs.org/docs/hello-world.html) を読んでみたところ色々な気付きがありました。独学で React を学んでいると気付かないようなことも多いと思いますので、今回はそういったテクニックについてまとめてみたいと思います。

なるべくこの記事では簡潔に記載し、より詳しく知りたければリンク先を読んでもらう形にしたいと思います。

なお、基本的には最新版の React 18 で動作確認をしています。

# React.Fragment

コンポーネントは JSX.Element を返す必要がありますが、[React.Fragment を使うことにより複数の要素をつなげて返すことができます。](https://ja.legacy.reactjs.org/docs/fragments.html)

```jsx
return (
  <>
    <h1>My Profile</h1>
    <p>I am an office worker.</p>
  </>
);
```

上記のコードは以下のコードの省略形です。

```jsx
return (
  <React.Fragment>
    <h1>My Profile</h1>
    <p>I am an office worker.</p>
  </React.Fragment>
);
```

ループ中で使う場合は React.Fragment に key 属性を指定します。

```jsx
{products.map((product) =>
  <React.Fragment key={product.id}>
    <h2>{product.name}</h2>
    <p>{product.description}</p>
  </React.Fragment>
}
```

# 論理 && 演算子による条件付きレンダー

[JSX では && 演算子を使用して以下のような書き方ができます。](https://ja.legacy.reactjs.org/docs/conditional-rendering.html#inline-if-with-logical--operator "条件付きレンダー – React")

```jsx
{ condition && expression }
```

たとえば今まで三項演算子で書いていたものを以下のように書けます。

```diff_jsx
  {notifications.length >= 0
-     ? <span class="badge">{notifications.length}</span>
-     : <></>
+     && <span class="badge">{notifications.length}</span>
  }
```

これは、JSX 中に書かれた式が false を返すと、React は何もレンダリングしないからです。他に true, null, undefined が返された場合も、何もレンダリングされません。

TypeScript と eslint を使用している場合は、[strict-boolean-expressions](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md) を有効にするのが良いそうです。

# event.target.name

React ではフォームの値が更新された場合に以下のようなイベントハンドラを書くことがあります。以下のサンプルコードでは、name と email を指定するテキストボックスがあり、それぞれの値が更新された場合にこれらの関数が呼ばれることを想定しています。

```jsx
const [name, setName] = useState('');
const [email, setEmail] = useState('');

function handleChangeName(event) {
  setName(event.target.value);
}

function handleChangeEmail(event) {
  setEmail(event.target.value);
}
```

[event.target.name を使うと、イベントハンドラをひとつにまとめることができるかもしれません。](https://ja.legacy.reactjs.org/docs/forms.html#handling-multiple-inputs "フォーム – React")

```jsx
const [formData, setFormData] = useState({ name: '', email: '' });

function handleChangeText(event) {
  const newFormData = {...formData};
  newFormData[event.target.name] = event.target.value;
  setFormData(newFormData);
}
```

なお、公式ドキュメントでは、[Computed property names](https://ginpen.com/2017/12/07/computed-property-name/ "動的にプロパティ名を設定できるようになりました。（現代的JavaScriptおれおれアドベントカレンダー2017 – 07日目）") を使用して書いていました。上の例を Computed property names を使用して書き換えると以下のようになるでしょう。

```jsx
function handleChangeText(event) {
  setFormData({...formData, [event.target.name]: event.target.value});
}
```

# select タグと textarea タグの value 属性

select タグと textarea に、HTML には本来存在しないはずの value 属性が追加されています。

https://ja.legacy.reactjs.org/docs/forms.html

また、`input[type="checkbox"]` と `input[type="radio"]` のタグにも checked 属性が指定できるようになっています。

https://ja.legacy.reactjs.org/docs/dom-elements.html

これにより、冗長なコードを省き、制御されたコンポーネントの管理を簡単に行うことが出来ます。

```jsx
<select value={selectedItem}>
  <option value="strawberry">イチゴ</option>
  <option value="mint">ミント</option>
  <option value="chocolate">チョコレート</option>
</select>
<textarea value={myVeryLongText} />
<input type="checkbox" checked={isChecked} />チェックボックス
```

# props.children

[React では children という特別な props を使うことができます。](https://ja.legacy.reactjs.org/docs/composition-vs-inheritance.html#containment) タグで囲まれた子要素は `props.children` として受け取ることができ、コンポーネントの内容として自由に配置することができます。

```jsx:ParentComponent.jsx
<FancyBorderComponent>
  <h1>Hello World</h1>
  Welcome to React!
</FancyBorderComponent>
```

```jsx:FancyBorderComponent.jsx
// コンテンツに派手なボーダーを追加する
function FancyBorderComponent(props) {
  return (
    <div class="fancy-border">
      {props.children}
    </div>
  );
}
```

TypeScript を使う場合は、props.children は React.Node 型を指定するのが良いでしょう。

# style の単位を省略すると px になる

CSS では 0 以外の数値の単位は省略できませんでしたが、Reactでは省略できます。

（なお、CSS プロパティによって、[単位が自動で付く場合と付かない場合があります](https://react.dev/reference/react-dom/components/common#common:~:text=You%20can%20pass%20strings%20or%20numbers%20as%20values.%20If%20you%20pass%20a%20number%2C%20like%20width%3A%20100%2C%20React%20will%20automatically%20append%20px%20(%E2%80%9Cpixels%E2%80%9D)%20to%20the%20value%20unless%20it%E2%80%99s%20a%20unitless%20property.)。string 型を指定しておくと間違いなく単位が付かないので、付けたくない場合はそれが確実だと思います。）

> You can pass strings or numbers as values. If you pass a number, like width: 100, React will automatically append px (“pixels”) to the value unless it’s a [unitless property](https://github.com/facebook/react/blob/81d4ee9ca5c405dce62f64e61506b8e155f38d8d/packages/react-dom-bindings/src/shared/CSSProperty.js#L8-L57).

https://react.dev/reference/react-dom/components/common

```jsx:JSX
<div style={{ height: 150, padding: 50, opacity: 0.5, backgroundColor: 'red' }}>
  Hello World!
</div>
<div className="hello-world">
  Hello World!
</div>
```

```css:CSS
.hello-world {
  height: 150px;
  padding: 50px;
  opacity: 0.5;
  background-color: blue;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78152/acc648d2-5d1b-d3f2-0c33-fb8b0d6d0942.png)

[カスタムプロパティでは自動で単位が付いてしまうという話もある](https://digipress.info/tech/avoid-react-automatically-append-px/)ようですが、自分の環境では再現できませんでした。

# カスタムフック

`useState` や `useEffect` などの hooks を使用する処理を別の関数に共通化することができます。[これはカスタムフックと呼ばれます](https://ja.legacy.reactjs.org/docs/hooks-custom.html)が、内部的にはただの関数です。

```jsx
function useCount() {
  const [count, setCount] = useState(0);

  const countUp = () => {
    setCount(count + 1);
  }

  const countMessage = `現在のカウントは ${count} です。`

  return [countMessage, countUp];
}
```

これらは他のフックと同じように関数コンポーネントから呼ばれます。

```jsx
function MyComponent() {
  const [countMessage, countUp] = useCount();

  return (
    <>
      { countMessage }
      <button onClick={countUp}>カウント</button>
    </>
  );
}
```

React を始めたばかりの頃は必要性を感じないかもしれませんが、いつか必要になったときに思い出してみてください。

# useState の setFoo() に関数を渡せる

```jsx
const [count, setCount] = useState(0);

var handleClick = () => {
  setCount((c) => c + 1);
}
```

`setFoo()` の引数として、新しい state を渡す代わりに、**古い state を受け取って新しい state を返す関数** を渡すことができるようです。最新の state を使うことが出来るので、連続して setFoo() を呼び出すこともできます。

```jsx
var handleClick = () => {
  setCount((c) => c + 1);
  setCount((c) => c + 1); // count の値が 2 増加する
}

var handleClickAlt = () => {
  setCount(count + 1);
  setCount(count + 1); // count の値は 1 しか増加しない
}
```

ただ、これを使わないといけないという場面はあまりないかも、と感じました。

# Context

Reactアプリケーション全体で使用されるようなグローバルな変数を作成することができます。たとえばロケール設定やUIテーマ設定などです。詳細はリンク先を確認してください。

https://ja.legacy.reactjs.org/docs/context.html

# Portal

ポータルを使うと、DOM 上で異なる位置に、子コンポーネントをレンダリングすることができます。たとえば、`overflow: hidden` が指定されているコンポーネント内でモーダルダイアログを表示したい場合などに使用できるそうです。

https://ja.legacy.reactjs.org/docs/portals.html

# まとめ

React の公式ドキュメントを読み、知らないことが多くて面白かったです。日本語だったのでこちらのドキュメントを読みましたが、少し古いようだったので、まだ最新のReactには知らない機能がたくさんあるかもしれません。逆に関数コンポーネントではあまり使われない機能の解説もあり、新鮮に感じました。これに関連して、この記事の内容と直接は関係ありませんが、フォロワーさんから頂いた興味深い記事のリンクを貼っておきます。React Hooks が発表された当時の様子が色々と書かれています。

https://logmi.jp/tech/articles/320434

もし何か間違いなどあればコメントお願いします！