Запоминаем выученное
Запустите код снова, и всё, что вы отметили, пропадёт: состояние живёт только пока работает приложение. Чтобы сохранить его, нужен localStorage, и хук для него у вас уже есть из урока «Рефы и собственные хуки». Он лежит в файле useLocalStorage.js:
export default function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
const saved = localStorage.getItem(key);
return saved === null ? initialValue : JSON.parse(saved);
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}Он используется так же, как useState, и возвращает такую же пару: значение и функцию, которая его меняет. Кроме того, он начинает с того, что сохранено под key, если там что-то есть, и сохраняет значение заново при каждом изменении. Поэтому менять нужно всего одну строку: useState([]) превращается в useLocalStorage("known", []). Это хук, поэтому он стоит в начале App, вместе с остальными хуками.
Ваши собственные слова тоже должны сохраняться. Но не сохраняйте все words: приложение при каждом запуске загружает их из words.json, и эффект всё равно заменил бы сохранённые. Вместо этого храните свои слова в отдельном состоянии, сохраняемом через useLocalStorage("ownWords", []), а колоду собирайте из обоих списков при отрисовке:
const deck = [...words, ...ownWords];Колода — не состояние, а вычисляемое значение, как счёт. Она должна стоять после проверки на null, потому что пока слова не пришли, ...words закончилось бы ошибкой. Ниже карточка, позиция, счёт и handleNext() работают уже с deck вместо words.
Задание
- 1
В
App.jsxимпортируйте хук (import useLocalStorage from "./useLocalStorage.js";) и создайте с его помощьюknown:const [known, setKnown] = useLocalStorage("known", []);. Отметьте слово кнопкой «Знаю» и запустите код снова: счёт его всё ещё учитывает. - 2
Храните свои слова в
const [ownWords, setOwnWords] = useLocalStorage("ownWords", []);и пустьhandleAdd()добавляет новое слово в конецownWords, а неwords. Нижеifсоздайтеdeck, как показано выше, и используйте его вместоwordsв остальной частиApp. Добавьте слово и запустите код снова: оно по-прежнему в колоде.