[[📗05 状態で広がるセカイ Ref編]] < [[📒Vue.jsクエスト]] > [[📗07 計算でテンプレートをシンプルに]]
## Abstract
[[リアクティブ]]にするための魔法は[[ref()]]だけではありません。[[reactive()]]の使い方を学びましょう。
## Lesson
[[reactive()]]で[[オブジェクト (JavaScript)|オブジェクト]]や[[配列 (JavaScript)|配列]]を包むと、それら全体が[[リアクティブ]]になります。
```html
<script setup lang="ts">
import { reactive } from "vue";
const state = reactive({
count: 1,
});
const handleClick = () => {
state.count *= 2;
};
</script>
<template>
<div>{{ state.count }}</div>
<div>NEXT: {{ state.count * 2 }}</div>
<button @click="handleClick">Double up</button>
</template>
```
上記は[[📗05 状態で広がるセカイ Ref編#Mission 3]]の回答例コードと同等の動きをします。
```html
<script setup lang="ts">
import { ref } from "vue";
const countState = {
count: ref(1),
};
const handleClick = () => {
countState.count.value *= 2;
};
const { count } = countState;
</script>
<template>
<div>{{ count }}</div>
<div>NEXT: {{ count * 2 }}</div>
<button @click="handleClick">Double up</button>
</template>
```
[[ref()]]を使うケースより階層が1つ深くなりますが、以下の点から[[reactive()]]をオススメしています。
- [[reactive()]]の中で[[プロパティ (TypeScript)|プロパティ]]ごとに[[ref()]]を呼び出す必要がない
- `<script>`、`<template>`の両方において`.value`を呼び出す必要がない[^1]
- 状態が集約され、状態であることが一目で分かる
また、[[reactive()]]はデフォルトで`Deep Reactivity`です。[[reactive()]]の中では[[オブジェクト (JavaScript)|オブジェクト]]や[[配列 (JavaScript)|配列]]を何度ネストさせても、すべての変更を期待通り検知します。
```ts
const obj = reactive({
nested: {
nested: {
ary: [{nested: {count: 1}}]
}
},
})
```
## Missions
### Mission 1
#🙂NORMAL
以下のコードを[[reactive()]]を使って書き直してください。
```html
<script setup lang="ts">
import { ref } from "vue";
const countSingle = ref(0);
const countDouble = ref(0);
const handleClick = () => {
countSingle.value++;
countDouble.value = countSingle.value * 2;
};
</script>
<template>
<div>{{ countSingle }} * 2 = {{ countDouble }}</div>
<button @click="handleClick">Increment</button>
</template>
```
%%
回答例
```html
<script setup lang="ts">
import { reactive } from "vue";
const state = reactive({
countSingle: 0,
countDouble: 0,
});
const handleClick = () => {
state.countSingle++;
state.countDouble = state.countSingle * 2;
};
</script>
<template>
<div>{{ state.countSingle }} * 2 = {{ state.countDouble }}</div>
<button @click="handleClick">Increment</button>
</template>
```
%%
### Mission 2
#😵HARD
以下を実行したとき、コンソール出力結果が`{hoge: "huga"}`に==ならない==理由を説明してください。
```html
<script setup lang="ts">
import { reactive } from "vue";
const state = reactive({
hoge: "huga"
});
console.log(state);
</script>
```
> [!hint]- Hint 1
> https://vuejs.org/guide/essentials/reactivity-fundamentals.html#reactive-proxy-vs-original-1
%%
回答例
[[reactive()]]の返却結果は引数として渡された[[オブジェクト (JavaScript)|オブジェクト]]の[[Proxy (JavaScript)|Proxy]]になるから。
%%
### Mission 3
#😱NIGHTMARE
[[Vue]]が[[#Mission 2]] 回答のような挙動になる背景を説明してください。
> [!hint]- Hint 1
> [リアクティブの探求 \| Vue\.js](https://v3.ja.vuejs.org/guide/reactivity.html#vue-%E3%81%8B%E3%82%99%E3%81%A8%E3%82%99%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%88%E3%82%99%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%AE%E3%81%8B%E7%9F%A5%E3%82%8B%E6%96%B9%E6%B3%95)
%%
回答例
[[リアクティブ]]を実現するには、[[Proxy (JavaScript)|Proxy]]を使って追跡や変更検知を行い、必要な時に必要な処理を再実行する必要があったから。
%%
## References
[Reactivity Fundamentals \| Vue\.js](https://vuejs.org/guide/essentials/reactivity-fundamentals.html)