Skip to content

Commit e44cdd4

Browse files
committed
feat: useCharacter composable
1 parent 4d81667 commit e44cdd4

File tree

6 files changed

+100
-68
lines changed

6 files changed

+100
-68
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "breakingbad",
2+
"name": "rick-and-morty",
33
"version": "0.0.0",
44
"private": true,
55
"scripts": {

src/characters/composables/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from './useCharacters';
1+
export * from './useCharacters.old';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { ref, onMounted } from "vue";
2+
import axios from "axios";
3+
4+
import rickAndMortyApi from "@/api/rickAndMortyApi";
5+
import type { Character, ResponseCharacter } from "@/interfaces/character";
6+
7+
// Global state
8+
const characters = ref<Character[]>([]);
9+
const isLoading = ref<boolean>(true);
10+
const hasError = ref<boolean>(false);
11+
const errorMessage = ref<string | undefined>();
12+
13+
export const useCharactersOld = () => {
14+
// With suspense
15+
// const { data } = await rickAndMortyApi.get<ResponseCharacter>('/character');
16+
// const characters = ref<Character[]>(data.results);
17+
18+
// Local state
19+
// const characters = ref<Character[]>([]);
20+
// const isLoading = ref<boolean>(true);
21+
22+
onMounted(async () => {
23+
await loadCharacters();
24+
});
25+
26+
const loadCharacters = async () => {
27+
if (characters.value.length) return;
28+
29+
try {
30+
isLoading.value = true;
31+
const { data } = await rickAndMortyApi.get<ResponseCharacter>(
32+
"/character"
33+
);
34+
characters.value = data.results;
35+
} catch (error) {
36+
hasError.value = true;
37+
if (axios.isAxiosError(error)) {
38+
return (errorMessage.value = error.message);
39+
}
40+
41+
errorMessage.value = JSON.stringify(error);
42+
} finally {
43+
isLoading.value = false;
44+
}
45+
};
46+
47+
return {
48+
characters,
49+
isLoading,
50+
hasError,
51+
errorMessage,
52+
};
53+
};
+37-35
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,55 @@
1-
import { ref, onMounted } from "vue";
2-
import axios from "axios";
1+
import { computed, ref } from "vue";
2+
import { useQuery } from "@tanstack/vue-query";
33

4-
import rickAndMortyApi from "@/api/rickAndMortyApi";
54
import type { Character, ResponseCharacter } from "@/interfaces/character";
5+
import rickAndMortyApi from '@/api/rickAndMortyApi';
6+
import { isAxiosError } from 'axios';
67

7-
// Global state
8+
// defined in the global state
89
const characters = ref<Character[]>([]);
910
const isLoading = ref<boolean>(true);
1011
const hasError = ref<boolean>(false);
11-
const errorMessage = ref<string | undefined>();
12+
const errorMessage = ref<string | null>(null);
1213

13-
export const useCharacters = () => {
14-
// With suspense
15-
// const { data } = await rickAndMortyApi.get<ResponseCharacter>('/character');
16-
// const characters = ref<Character[]>(data.results);
14+
const getCharacters = async (): Promise<Character[]> => {
15+
if (characters.value.length) return characters.value;
16+
const { data } = await rickAndMortyApi.get<ResponseCharacter>("/character");
17+
return data.results;
18+
};
1719

18-
// Local state
19-
// const characters = ref<Character[]>([]);
20-
// const isLoading = ref<boolean>(true);
20+
const loadCharacters = (data: Character[]) => {
21+
hasError.value = false;
22+
errorMessage.value = null;
23+
characters.value = data;
24+
isLoading.value = false;
25+
};
2126

22-
onMounted(async () => {
23-
await loadCharacters();
27+
const loadError = (error: unknown) => {
28+
hasError.value = true;
29+
if (isAxiosError(error)) {
30+
errorMessage.value = error.response?.data.error;
31+
}
32+
isLoading.value = false;
33+
}
34+
35+
const useCharacters = () => {
36+
const {} = useQuery(["characters"], getCharacters, {
37+
onSuccess: loadCharacters,
38+
onError: loadError,
2439
});
2540

26-
const loadCharacters = async () => {
27-
if (characters.value.length) return;
28-
29-
try {
30-
isLoading.value = true;
31-
const { data } = await rickAndMortyApi.get<ResponseCharacter>(
32-
"/character"
33-
);
34-
characters.value = data.results;
35-
} catch (error) {
36-
hasError.value = true;
37-
if (axios.isAxiosError(error)) {
38-
return (errorMessage.value = error.message);
39-
}
40-
41-
errorMessage.value = JSON.stringify(error);
42-
} finally {
43-
isLoading.value = false;
44-
}
45-
};
46-
4741
return {
42+
// properties
4843
characters,
4944
isLoading,
5045
hasError,
5146
errorMessage,
47+
48+
// getters
49+
count: computed(() => characters.value.length),
50+
51+
// methods
5252
};
5353
};
54+
55+
export default useCharacters;

src/characters/pages/CharacterList.vue

+7-30
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,19 @@
11
<script setup lang="ts">
2-
import { useQuery } from "@tanstack/vue-query";
3-
4-
import rickAndMortyApi from "@/api/rickAndMortyApi";
5-
62
import CardList from "@/characters/components/CardList.vue";
7-
8-
import type { Character, ResponseCharacter } from "@/interfaces/character";
9-
import characterStore from "@/store/characters.store";
3+
import useCharacters from "../composables/useCharacters";
104
115
const props = defineProps<{ title: string; visible: boolean }>();
12-
13-
14-
const getCharactersCacheFirst = async (): Promise<Character[]> => {
15-
if (characterStore.characters.count) return characterStore.characters.list;
16-
const { data } = await rickAndMortyApi.get<ResponseCharacter>("/character");
17-
return data.results;
18-
};
19-
20-
// const { isError, isLoading, error, data,} =
21-
useQuery(["characters"], getCharactersCacheFirst, {
22-
onSuccess: (characters) => {
23-
characterStore.loadCharacters(characters);
24-
},
25-
// onError: (error) => {
26-
// },
27-
});
28-
29-
6+
const { isLoading, hasError, errorMessage, characters, count } = useCharacters();
307
</script>
318

329
<template>
33-
<h1 v-if="characterStore.characters.isLoading">Loading...</h1>
34-
<h1 v-else-if="characterStore.characters.hasError">
35-
{{ characterStore.characters.errorMessage }}
10+
<h1 v-if="isLoading">Loading...</h1>
11+
<h1 v-else-if="hasError">
12+
{{ errorMessage }}
3613
</h1>
3714
<template v-else>
38-
<h2>{{ props.title }}</h2>
39-
<CardList :characters="characterStore.characters.list"/>
15+
<h2>{{ props.title }} - {{ count }}</h2>
16+
<CardList :characters="characters" />
4017
</template>
4118
</template>
4219

src/main.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import router from "./router";
44
import { VueQueryPlugin } from "@tanstack/vue-query";
55

66
import "./assets/main.css";
7-
import "@/store/characters.store"
7+
// import "@/store/characters.store"
88

99
const app = createApp(App);
1010

0 commit comments

Comments
 (0)