Saving Habits
Check a few habits off and click Run again. Everything is as it was at the start: each time the page opens, the app starts from the beginning and loads the file again. A tracker that forgets what you've done is no use, so it'll save the habits in localStorage.
In the lesson Composables, you wrote a composable for that, useLocalStorage(key, initial). It gives back a ref, as ref() does, but the ref starts with what's saved under the key (or with initial when nothing has been saved yet), and a watcher saves it whenever it changes. It goes in a file of its own, useLocalStorage.js, in the third tab:
import { ref, watch } from "vue";
export function useLocalStorage(key, initial) {
const saved = localStorage.getItem(key);
const value = ref(saved === null ? initial : JSON.parse(saved));
watch(
value,
(newValue) => {
localStorage.setItem(key, JSON.stringify(newValue));
},
{ deep: true },
);
return value;
}
{ deep: true } matters here: checking a habit off changes a done deep inside the array, not the array itself, and without it, the watcher wouldn't notice.
In App.vue, habits now comes from the composable instead of ref(), saved under the key "habits". The rest of the code can stay as it is, because habits is still a ref with an array:
import { useLocalStorage } from "./useLocalStorage.js";
const habits = useLocalStorage("habits", []);
When the app starts with saved habits, it mustn't load the file over them. So onMounted loads the file only when there are no habits: the first time the app opens, or after you've removed them all, when the suggestions come back.
onMounted(async () => {
if (habits.value.length === 0) {
const response = await fetch("habits.json");
if (!response.ok) {
error.value = "The habits couldn't be loaded.";
} else {
habits.value = await response.json();
}
}
loading.value = false;
});
Here, the preview keeps what the page saves while you work on the exercise. Once something is saved, the console shows a Clear saved data button, which opens the page again as if for the first time.
Instructions
- 1
In
useLocalStorage.js, write the composable from above. InApp.vue, import it and createhabitswith it, as above. As soon as the habits have loaded, the console shows Clear saved data: the composable has saved them. (Clicking Run still brings back the habits from the file; the next step fixes that.) - 2
Change
onMountedas above, so that it loads the file only when there are no habits. Check two habits off, remove one and click Run: the list stays as you left it. To start again from the file, click Clear saved data.