Story Time: Moodle Quizzes

Some years ago, I used an open source LMS called Moodle (comparable to Blackboard or Canvas, if you’ve heard of those). At the time, it was not the prettiest, but it worked well enough, and the school could not complain about the price. I really only had one complaint.

When taking a test/quiz in Moodle, it would pop up a reminder about how much time you had left. Not the smoothest user experience (UX), but understandable at the time. However, if you were typing a response, the text area would suddenly be de-selected. That meant your next keystrokes were interpreted as shortcut keys.

At the time, hitting backspace in Chrome sent you back a page.

This meant every 30 minutes, the reminder window would try to trick you into going back a page. If it succeeded, then when you re-entered the test all your submission answers — hours worth of work — would be gone.

I’ve had it happen 3 times in a row once. Tears. Not hard to imagine that becoming “I hate Math”, “I hate learning online”, “I hate computers”, then “I hate school” with smaller kids.

To say “Awful UX” would be a gross understatement.

useLocalStorage

Sync state to local storage so that it persists through a page refresh. Usage is similar to useState except we pass in a local storage key so that we can default to that value on page load instead of the specified initial value.

import { useState } from 'react';



// Usage

function App() {

  // Similar to useState but first arg is key to the value in local storage.

  const [name, setName] = useLocalStorage('name', 'Bob');



  return (

    <div>

      <input

        type="text"

        placeholder="Enter your name"

        value={name}

        onChange={e => setName(e.target.value)}

      />

    </div>

  );

}



// Hook

function useLocalStorage(key, initialValue) {

  // State to store our value

  // Pass initial state function to useState so logic is only executed once

  const [storedValue, setStoredValue] = useState(() => {

    try {

      // Get from local storage by key

      const item = window.localStorage.getItem(key);

      // Parse stored json or if none return initialValue

      return item ? JSON.parse(item) : initialValue;

    } catch (error) {

      // If error also return initialValue

      console.log(error);

      return initialValue;

    }

  });



  // Return a wrapped version of useState's setter function that ...

  // ... persists the new value to localStorage.

  const setValue = value => {

    try {

      // Allow value to be a function so we have same API as useState

      const valueToStore =

        value instanceof Function ? value(storedValue) : value;

      // Save state

      setStoredValue(valueToStore);

      // Save to local storage

      window.localStorage.setItem(key, JSON.stringify(valueToStore));

    } catch (error) {

      // A more advanced implementation would handle the error case

      console.log(error);

    }

  };



  return [storedValue, setValue];

}

#react-hook #javascript #web-development #react

useLocalStorage() React Hook
55.55 GEEK