Reputation: 1773
Using the onMount photo example in the svelte docs, I can use my own rest api (yet another todo ..) to display data. I changed it to put the photo html in a separate component and it works. Here is App.svelte
<script>
import { onMount } from 'svelte'
import Photos from './Photos.svelte'
let photos = []
onMount(async () => {
const res = await fetch('http:///mint20-loopback4:3000/todos');
photos = await res.json();
console.log('todolist : ', photos)
})
</script>
<Photos bind:photos={photos}/>
I then took the MDN svelte tutorial and went through that. Later, I removed the todo initial list from the store and added an onMount fetch in App.svelte. The result is an empty todo list but when I interact with the app, the data is displayed.
Here is the console output
Todos.svelte with length of : 0
into TodoStatus.svelte : Array []
totalTodos : undefined
completedTodos : undefined
Todos length - mounted : 0
todolist : Array(7) [ {…}, {…}, {…}, {…}, {…}, {…}, {…} ]
completed mount : Array(7) [ {…}, {…}, {…}, {…}, {…}, {…}, {…} ]```
And App.svelte
<script lang="ts">
import Todos from './components/Todos.svelte'
import Alert from './components/Alert.svelte'
import { onMount } from 'svelte'
import type { TodoType } from './types/todo.type'
let initialTodos: TodoType[] = []
onMount(async () => {
const res = await fetch('http:///mint20-loopback4:3000/todos');
const json = await res.json();
console.log('todolist : ', json)
json.forEach(element => {
let t: TodoType = { id: 0, title: '0', isComplete: true }
t.id = element.id
t.title = element.title
if (element.isComplete === undefined) {
t.isComplete = false
}
else {
t.isComplete = element.isComplete
}
initialTodos.push(t)
})
console.log('completed mount : ', initialTodos)
})
</script>
<Alert />
<Todos bind:todos={initialTodos} />
So it does as expected in the photos example but not in this where the empty array is passed on instead before the onMount. The todo example has a lot more components than photos which just has the single component but, suffice to say, I am confused. What do I have to do get the initial screen to use the populated data?
Just to add - I included console logging in photos and that too has the same pattern - first child component logs and finally the onMount in App.svelte. And yet here, the data is correctly displayed.
So I think is supposed to happen is that because changes to the array are dynamically reflected in the display, when the array is updated, so is the display. But in todos this is not happening.
Upvotes: 1
Views: 2428
Reputation: 1234
The DOM is only updated on variable assignments. In your example, you're using the .push() method to add an object to the array. So you'll need to add this after your forEach loop to ensure the component gets the updates:
initialTodos = initialTodos;
Another option is to do this inline. You can replace:
initialTodos.push(t)
with
initialTodos = [...initialTodos,t]
Here is the official docs around this.
Upvotes: 1