ivan quintero
ivan quintero

Reputation: 1272

How to hold off rendering until ajax call completes

I am refactoring a React app that loads the language labels from a json file on the server. The data is pulled from the server using an Ajax call, which updates a store that contains all the language labels. Here is some code illlustrating the problem.

app.js

<script>
import { storeLang, getLangLabels } from './store'

// get labels from server
getLangLabels()

// set language labels in a reactive variable
$: LABELS = $storeLang.labels
</script>

<div>
 <h2>{LABELS.title}</h2>
</div>

Here is how the store is setup. The ajax call updates the store with the labels.

store.js

import { writeable } from 'svelte/store'

export const storeLang = writeable({})

export const getLangLabels = () => {
  return fetch('lang.json').then( data => {
  storeLang.set(data);
})
}

However, when I run the application I do not have access to the LABELS variable yet, nor it is updated when the fetch call is resolved. Here is the error message.

Uncaught ReferenceError: Cannot access 'LABELS' before initialization

The way I solved this problem in React was to render the entire <App /> only after the language labels where fetched from the server. I have not figured out a way to solve this using Svelte.

Please advise.

Solution

Following @tehshrike recommendation, I setup the getLang as an async function and using an await block on the App.svelte component, which is the entry point of the app. This way, when the promise resolves after getting the language labels, the App renders (code abbreviated for illustration purposes).

App.svelte

<script>
import { getLang } from './lang/store.js';

let promise = getLang();
</script>

{#await promise}
  Loading language labels
{:then value}
  // we don't use the returned value because the labels are stored in 
  // the store and the subscribed components react accordingly
  <Header />
  <Sidebar />
  <Main />
{:catch}
  Error resolving promise
{/await}

Upvotes: 2

Views: 1387

Answers (1)

TehShrike
TehShrike

Reputation: 10074

If you put your promise into the store itself, instead of waiting for the promise to resolve before putting the value into the store, you can use an await block and reference $storeLang.labels without needing to set up a reactive declaration inside your component.

Upvotes: 2

Related Questions