React・Vue 面倒くさい所

# React
## `useState`のクロージャー地獄
`useState`は再描画ごとに呼び出される関数内で保持されてる`state`と代入関数を返す関数ですが、返しているこの値は勝手に変わりません。
再描画によってコンポーネント関数が呼び出され、その中で`useState`が呼び出されて初めてその関数の[クロージャー](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Closures)内でのみ更新されます。
クロージャー内で値が更新されても、その外の値は更新されません。
例えばこれです。
```tsx:App.tsx
import { useState } from "react";

export const App = () => {
    const [count, setCount] = useState(0);
    function add(){
        setCount(count + 1);
        setTimeout(() => console.log(count), 1000);
    }
    return <div className="app">
        <button onClick={add}>{count}</button>
    </div>
}

```

https://reactplayground.vercel.app/#N4IgLgziBcBmCGAbCBTANCAbrK1QEsA7AExQA8A6AK1xHwFsAHAewCcwACYDgQUcY4BfDrFbN6HAOQUA9H0bUIZSQB1CDFuw4AlFPADGnUeKms9h1eqZtO3fWfhgU25s07DjEyQ8MBaYuIy+oj4KIRglmr6zIQQnNHh8EQorBwAvBwB+gCu9GFgFADmKGAAoogoeeEAQgCeAJLEABTerhEAlFExcRxibukc9npOLm5NCWBJhCmdhH0FZiQpTWocOuYFQ44o5ZX5K4Rra7oGBQDKYKz4hgCyzKRoq0eE2YiIj4dHJ4YUW067VTATXkszWs3aIAw8kUZBgdGsWm+YDQXA42VQF22QhEYgkKhAPjA+IA3Go1ORNPFupx5AMmu10gA+LhPBI9ADa0Wy4RRqDAAGFmNywABdAbolCYpxNAAM7VJn1g3MM+BiHHgxGaDOATzWfMFwvGQvCHAA1BwAIzy3UcPkAFQYKCFQPpTMG3WYFQoiGYhSNwvaKItMpD1s+gieZjA2VYhwORw4AB5iPhMINEPAIBAAHLwPJpfHwfj4xk2taJgBG2TAYDVMX5IX0AGs0sANcRBIzgFzwoJEzIqzWYqXPuWZCnMCOwQrBArISA4rUvfos3CKBWwIcdYqYmBfBB8AAvFDQDgAJjM9BnIEEgiAA

setTimeoutを介すとクロージャーの外になるので、更新されず前の値が`console`に出てきます。

対処法はあります。
### 代入関数の活用
TypeScriptだと変数の初期値がデフォルトになっていて面倒くさいです。
それに加え、取得するたびに再描画がされてしまいます。
```ts
let newCount = 0;
setCount(count => newCount = count);
console.log(newCount);
```
### カスタムフック
このようにすると、上の色々を省略できます。
しかし上と同じく取得に再描画が必要です。
```ts:usestate.ts
import React from "react";

export const useState = <T>(defaultState: T) => {
    const [state, setState] = React.useState(defaultState);
    const getState = (): T => {
        let _state;
        setState(newState => _state = newState);
        return _state;
    }
    return [state, setState, getState];
}

```
```tsx:App.tsx
import { useState } from "./usestate.js";

export const App = () => {
    const [count, setCount, getCount] = useState(0);
    function add(){
        setCount(count + 1);
        setTimeout(() => console.log(getCount()), 1000);
    }
    return <div className="app">
        <button onClick={add}>{count}</button>
    </div>
}

```

https://reactplayground.vercel.app/#N4IgLgziBcBmCGAbCBTANCAbrK1QEsA7AExQA8A6AK1xHwFsAHAewCcwACYDgQUcY4BfDrFbN6HAOQUA9H0bUIZSQB1CDFuw4AlFPADGnUeKms9h1eqZtO3fWfhgU25s07DjEyQ8MBaYuIy+oj4KIRglmr6zIQQnNHh8EQorBwAvBwB+gCu9GFgFADmKGAAoogoeeEAQgCeAJLEABTerhEAlFExcRxibukc9npOLm5NCWBJhCmdhH0FZiQpTWocOuYFQ44o5ZX5K4Rra7oGBQDKYKz4hgCyzKRoq0eE2YiIj4dHJ4YUW067VTATXkszWs3aIAw8kUZBgdGsWm+RjEEhUIB8YDRAG41BobFwONlUBdtkIRCiOGjZESUHFtopsWo1ORNPFupx5AMmu10gA+LhPNYJHoAbWi2XCaA4qDAAGFmBKwFLinKFeEALoDGkkpxNAAM7RxnzWsAlhnwMQ48GIzXawEFRzWMvlivGas4AGoOABGQ0Ox0ygAqDBQCqB3L5g26zAqFEQzEKTRVLvC3PaUu9eqzfuNQgdZjA2VYhwAPMR8JhBoh4BAIAA5eB5NJo+D8NG8-1HEsAI2yYDAlpispC+gA1mlgNbiIJecBxeFBCWZL3+zEO7ml+XMOvBGpISA4rVY-pa3CKN2wId7Z9YDEwL4IPgAF4oaAcABMZnoRsE+5pdKcRQ4TxRENnJEw0QxRlCGZMhWSjWJOG1SYnC5UgEFeMAdRQHk0n5a9HWFTgRQA9BpRKbDNQyJEKGQ7YmnQ+BMOwnNCPZDgVWwrlcPwzs1gqTgAH1SKNR0AwolCUCaaYAHcuLwjhhMkgZZJY0SxLWAsi0OJTtnUtZd1zLTiw4EjJKlGVsOVCTtnVH890EQQgA

なぜかうまくいきませんでした。

`useRef`で再描画できればなあ

## メモリ食いそう
下手したらクロージャーが大量に出来るのでメモリ食いそうです。

# Vue
## テンプレートでそのままグローバル変数を使えない
Vueで以下のようにグローバル変数を参照しようとすると、エラーが発生します。

```vue:App.vue
<script setup>
import { ref } from 'vue'

const msg = ref('Hello World!')
</script>

<template>
  <h1>{{ btoa(new Date().toString()) }}</h1>
  <input v-model="msg" />
</template>

```

https://play.vuejs.org/#eNp9kT1PwzAQhv/K4SWJVBIhmKq0Eh+VgAEQRWLxEtJrmuLYln1pK0X571xctXSoutn3vD4/Z3fi3tp006IYi9yXrrYEHqm1U6nrxhpH0IHDJfSwdKaBiKOR1FKXRnuCxlcwGXgcPaNSBr6NU4urKJE6z/btuBFvCBurCkLeAeSrm2nXwQ+ZIta4hScGcZKSmZOrdRUnCfR9nnEqpGttW4LNdWMWqCZS8KVSQMYwz076ipEgz1rLukrX3mieqBvOS1GaxtYK3bulmrWlGEMgAyvYevsaauRaHB3q5QrL3zP1td8NNSk+HHp0G5TiyKhwFdIez+ZvuOP1EbJ9qzh9AX6iN6odHPexh1YvWPskF2xfwr/wQ3352Y5Q+8NQg+iQ7ENeCv6rxwuj/+vepnfhnNS96P8AIdiu9w==

この場合`btoa`がエラーの原因です。
### 対処法 変数を作る
このようにすれば一発で解決です。
コンポーネントの`data`に保存されるためです。
しかし`bind`が必要で面倒くさいのと、Web APIを保存するのは無駄を感じます。

```vue:App.vue
<script setup>
import { ref } from 'vue'

const msg = ref('Hello World!')
const btoa = window.btoa.bind(window);
</script>

<template>
  <h1>{{ btoa(new Date().toString()) }}</h1>
  <input v-model="msg" />
</template>

```

https://play.vuejs.org/#eNp9kd9LwzAQx/+VMy9tYbaIPs1u4I+B+qDiBF/y0rW3rrNNQpKug9L/3UvK5gTZW+6+nwufS3p2p1S8a5FNWWpyXSkLBm2r5lxUjZLaQg8a1zDAWssGAkIDLrjIpTAWGlPCzOVh8IR1LeFL6rq4CKIDsLIyI6KrRCG72FXxis7h2IhuuUiSP2SYRTCbQ0ZJmoxCpEKFxUbVmUWqANLN1bzv/UwosINHCsIotnJpdSXKMIpgGNKEKE9XQrUWdpeNLLCecUbanEFCYZqc3MsmzBqyWVdlvDVS0Jv0bp6zXDaqqlG/KVuRLWdT8InLMtq7e/E9q1ucHPr5BvPvf/pbs3c9zt41GtQ75OyY2UyXaMd4sXzFPZ2PIdm3NdFnwg80sm6d44jdt6Ig7RPO2z77n6WH+jSLvUVhDks5UUcOnueMfvvhzOq/utfxjZ/jYmDDD22RxSE=

# 結論
Reactの`useState`が返す値は勝手に変わらないので他クロージャーに値を渡すときなどに注意
Vueはテンプレートでそのまま使えないグローバル変数がある

個人としてはReactのようにJavaScriptに近いものが好きなのでReactにVueのプロキシベース変数を足してさいきょうのフレームワークが欲しい