2022年の React/Next.js 振り返り

:christmas_tree: Happy Merry Christmas! :christmas_tree:

今日はときめきのクリスマスイブです！
クリスマスマーケットに行って:wine_glass:ホットワイン:wine_glass:でも飲みたいですね:blush:
みなさんも楽しいクリスマスをお過ごしください！

さて、今年も残り一週間となりましたね。

今年はReact/Nextjsを使って新規開発をしていたら、
**React18がリリース**されたり、
**Next.js13が発表**されたり
新規プロジェクトでは今までと違う状態管理(**Zustand**)を導入してみたりして
勉強しながら、試行錯誤しながら楽しく開発出来た年でした。

その中でよかったな...と思う機能を少しご紹介したいと思います。

## 1. React18で追加されたパフォーマンス向上してくれる機能
React18ではいろんな機能が追加・改善されましたが、その中でパフォーマンスを向上してくれる以下の機能を紹介します。

### 1) レンダリングのbatch機能
今まではstateが変更する度に再レンダリングしたのが、stateが全部更新されてから再レンダリングされることが可能になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584614/953575df-9cb6-0983-bd55-334f5b8d6479.png)


https://github.com/reactwg/react-18/discussions/21

### 2) useTransition
例えばレンダリング処理が多くて画面が重くなる時を無理やり作ってみました。
```typescript
import { useState } from 'react';

// 配列10000個を作っちゃった＞＜ <=こら！
const a = new Array(10000).fill(0)

function App() {
  const [ name, setName ] = useState('');
  return (
    <div className="App">
      // タイピングするたびに10000配列のレンダリングを行うとしたら？
      <input onChange={(e) => { setName(e.target.name) }} />
      {a.map(() => {
        return <div>{name}</div>
      }}
    </div>
  )
}
```
↓
- useTransitionを使て解決しよう
- startTransitionで問題を起こすstateを囲む
```diff
- import { useState } from 'react';
+ import { useState, useTransition } from 'react';
const a = new Array(10000).fill(0)
function App() {
  const [ name, setName ] = useState('');
+ const [ isPending, startTransition ] = useTransition();
  return (
    <div className="App">
-     <input onChange={(e) => { setName(e.target.name) }} />
+     <input onChange={(e) => {
+       startTransition(() => {
+         setName(e.target.name)　<= 問題を起こしているstate
+       })
+     }} />
-     {a.map(() => {
-       return <div>{name}</div>
-     }}
+     {
+       isPending ? <>Loading...</> :
+       a.map(() => {
+           return <div>{name}</div>
+       }
+     }
    </div>
  )
}
```
今の画面を残しつつ次の画面を裏でレンダリングしてくれます。素晴らしい:clap_tone2:

### 3) useDeferredValue
上の問題をuseDeferredValueを使って解決してみよう
```diff
- import { useState } from 'react';
+ import { useState, useDeferredValue } from 'react';
const a = new Array(10000).fill(0)
function App() {
  const [ name, setName ] = useState('');
+ const state = useDeferredValue(name) 
  return (
    <div className="App">
      <input onChange={(e) => { setName(e.target.name) }} />
      {a.map(() => {
-        return <div>{name}</div>
+        return <div>{state}</div>
      }}
    </div>
  )
}
```
useDeferredValueは値の変化をいい感じに延期してくれます。これも素晴らしい:clap_tone2:

## 2. Zustandを使ったシンプル過ぎる状態管理
いままでredux-sagaやredux-toolkitを使って状態管理を行っていたのですが、
zustandを知って調べてみたら、今までより圧倒的にシンプルで分かりやすく
これは新しいプロジェクトに使ってみたい！と思って、導入を試しました。

https://docs.pmnd.rs/zustand/getting-started/introduction

導入方法はとてもシンプルです。

- storeの生成
- storeの作成には`create`を使う
- `create`は`set`, `get`を引数に取る
- `set`はstateを更新、`get`はstateを取得する
```typescript
import create from 'zustand';

const useStore = create((set, get) => ({
  count: 1,
  addCount: () => set((state) => ({ count: state.count + 1 })),
  resetCount: () => set(() => ({ count: 1 })),

  userList: [],

  // 非同期処理もstore内部で簡単に書ける
  fetchUserList: async () => {
    const res = await fetchData();

    // getでstateを取得
    set({ data: get().userList.concat(res.data) });
  },
}))

export default function Counter() {
  const { count, addCount, resetCount } = useStore();
  return (
    <div className="counter">
      <span>{count}</span>
      <button onClick={addCount}>+1</button>
    </div>
  );
}
```
複数のstoreを生成＆利用ももちろん可能です。
```typescript
const useAuthStore = create((set, get) => ({ ... });
const useCountStore = create((set, get) => ({ ... });
export default function App() {
  const { authInfo } = useAuthStore();
  const { count, addCount } = useCountStore();
  return (
    <div className="main">
      ...
    </div>
  );
}
```
今のところ無難に開発出来て、学習コストも低くて、コードもシンプルになるので、しばらくは愛用しそうです。
みなさんも是非使ってみてください。

## まとめ
最初Reactを触れた時はわからないことが多かったですが、どんどん機能も追加＆改善され、開発が楽しくなりました。
さらに10月に発表された[Next.js13](https://nextjs.org/blog/next-13)では新しいバンドルツール（Turbopack)や新しいRouting Systemなど、大きな進化があるようで(この内容に関しては別の記事で触れたいと思います)まだまだ楽しみが続きそうですね。

この勢いで年末年始休みにはReactやFlutterを使って何かアプリを開発したいと思ったりしてます。
では、今年も残りわずかですが、有意義な時間をお過ごしください。