State lives in the page's memory: reload the page and every useState starts over. The browser keeps a small store for each site that survives a reload: localStorage. It keeps text under a key, so values go in through JSON.stringify and come back out through JSON.parse. getItem gives null when nothing is saved under the key:
localStorage.setItem("theme", JSON.stringify("dark"));
JSON.parse(localStorage.getItem("theme")); // "dark"
localStorage.getItem("fontSize"); // null: nothing saved
Reading localStorage on every draw would be wasted work. When you give useState a function, React calls it on the first draw only and keeps what it returns, as in useState(() => countWords(book)). Saving touches something outside React, so it goes in an effect that runs when the value changes.
App already calls useLocalStorage("inStockOnly", false) for the "In stock only" box and uses what it returns like the pair from useState. In the starting code, the hook is empty and returns nothing, so App can't unpack it: Check prints a TypeError and your page starts empty. Check clicks the box, looks into localStorage, then reloads the page:
> open the page checkbox "In stock only": off text: 8 products > click "In stock only" checkbox "In stock only": on text: 7 products > the browser's localStorage inStockOnly = true > reload the page checkbox "In stock only": on text: 7 products
Your task: in src/useLocalStorage.js, make value start from what is saved under key (or initial when nothing is), save it in an effect whenever it changes, and return [value, setValue].
Assignment
Follow the Coding Tutorial to write the useLocalStorage hook: a state that reads localStorage once, an effect that writes to it, and the pair App uses.
Hint
Check for null before you call JSON.parse: that's the first visit, and initial is the answer. The effect's dependencies are [key, value].
Free plan: 30 tutor messages. PRO is unlimited.
