Better way to create dynamic menus?

I have - with some help :slight_smile: - managed to create fully dynamic menus. As a web newbie I have the ability to complicate things that may be done in a simpler way.

The main thing I do is to load the menu into localStorage and take it from there.

Is there simpler or better ways to do this or am I on the right track?

I know exactly what you mean there and still do it. Only for someone to comment ,‘Why didn’t you just do this instead?’

I am a busy today, and there is a bit to go through there. I have to say I like that you have created many short functions, rather than a few difficult to break down ones.

Having a cursory look though I would prefer a more loosely coupled getStatus function.

function getstatus() {
  let url = 'https://api3.go4webdev.org/status/lang/' + localStorage.lang
  fetch(url)
    .then((response) => response.json())
    .then(status)
    .catch(error => console.log(error))
}

A function that maybe you pass the language into and which returns a promise.

Perhaps something like the following.

function getStatusJson(language = 'en') {
  // return the promise
  return fetch(`https://api3.go4webdev.org/status/lang/${language}`)
    .then((response) => response.json())
    .catch((error) => console.error(error))
}

const setStatus = function(data) {
  localStorage.setItem('status', JSON.stringify(data))
  return data // might be useful?
}

const getStatus = function() {
  return JSON.parse(localStorage.getItem('status'))
}

window.addEventListener('DOMContentLoaded', function () {
  // just for demonstrating
  const chosenLanguage = 'de'

  getStatusJson(chosenLanguage)
    .then(setStatus)
    .then(getStatus)
    .then(console.log)
  // ...
})

Alternatively going down the async/await route

A more general and re-usable getJson function

const getJson = async function(url) {
  try {
    const response = await fetch(url)

    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`)
    }

    return await response.json()
  } catch(error) {
    console.error(error)
  }
}

and

const setStatus = function(data) {
  localStorage.setItem('status', JSON.stringify(data))
  return data
}

const getStatus = function() {
  return JSON.parse(localStorage.getItem('status'))
}

// Note use of async and await
window.addEventListener('DOMContentLoaded', async function () {
  const language = 'de'
  const response = await getJson(`https://api3.go4webdev.org/status/lang/${language}`)
  
  setStatus(response)
  console.log(getStatus())
  // ...
})

Note this is only as I say from a cursory look. I’m sure others here may have something to contribute or have different ideas :slight_smile:

edit: Just for reference here is the codepen I was playing with. You will need to click on console to see the output.

1 Like

Thank you for your input. Appreciated.

I am not sure I understand the dynamic part here. How should I set a global language or theme for the entire site when omitting the localStorage?

1 Like

My code was purely for illustrating a different approach to getting the json data and working with it.

I was going to add a comment next to the const language = 'de'. As I say I haven’t the time right now to dig deeper into your code, but that right side of the language assignment could obviously be something else, a call to a function or whatever.

Just a follow up, this is the updated code and codepen

// A standard fetchJson utility function (opted for a different name)
const fetchJson = async function(url) {
  // ...same code as before
}

// These are now general functions that set and get localStorage props
const storeProperty = function(key, prop) {
  localStorage.setItem(key, JSON.stringify(prop))
  return prop
}

const getProperty = function(key) {
  return JSON.parse(localStorage.getItem(key))
}

window.addEventListener('DOMContentLoaded', async function () {

  // localStorage.getItem returns a string or null
  // Always worth checking MDN to see what the return values are.
  const language = getProperty('language') || 'en'
  const response = await fetchJson(
   `https://api3.go4webdev.org/status/lang/${language}`
  )
  
  storeProperty('status', response)
  console.log(getProperty('status'))
  // ...
})
1 Like