Chain a DataSource refetch

Call .then() on APICall.execute() to trigger a DataSource refetch after a mutation completes.

When a user action changes server data — liking a post, adding a comment — the displayed list needs to reflect the change. Because execute() returns a Promise, you can chain .then(() => dataSource.refetch()) to re-fetch the list as soon as the write succeeds — without relying on blanket cache invalidation.

<Component name="SocialButton">
  <Button
    borderRadius="50%"
    icon="{$props.icon}"
    variant="outlined"
    themeColor="{$props.themeColor || 'secondary'}"
    size="xs"
    onClick="{emitEvent('click')}" />
</Component>
<App>
  <APICall
    id="favoritePost"
    method="post"
    url="/api/posts/{$param}/favorite" />
  <APICall
    id="unfavoritePost"
    method="post"
    url="/api/posts/{$param}/unfavorite" />
  <DataSource
    id="timelineData"
    url="/api/timeline"
    method="GET" />
  <VStack>
    <H3>Social Media Timeline</H3>
    <Items data="{timelineData}">
      <Card>
        <VStack>
          <H4>{$item.author}</H4>
          <Text>{$item.content}</Text>
          <HStack verticalAlignment="center">
            <HStack verticalAlignment="center">
              <SocialButton icon="reply" />
              <Text>{$item.replies_count}</Text>
            </HStack>
            <HStack verticalAlignment="center">
              <SocialButton icon="trending-up" />
              <Text>{$item.reblogs_count}</Text>
            </HStack>
            <HStack verticalAlignment="center">
              <SocialButton
                icon='like'
                themeColor="{$item.favourited ? 'attention' : 'secondary'}"
                onClick="() => {
                  if ($item.favourited) {
                    unfavoritePost.execute($item.id)
                    timelineData.refetch();
                  } else {
                    favoritePost.execute($item.id)
                    timelineData.refetch();
                  }
                }
                " />
              <Text variant="caption">{$item.favourites_count}</Text>
            </HStack>
          </HStack>
        </VStack>
      </Card>
    </Items>
  </VStack>
</App>
Click the Like button
<Component name="SocialButton">
  <Button
    borderRadius="50%"
    icon="{$props.icon}"
    variant="outlined"
    themeColor="{$props.themeColor || 'secondary'}"
    size="xs"
    onClick="{emitEvent('click')}" />
</Component>
<App>
  <APICall
    id="favoritePost"
    method="post"
    url="/api/posts/{$param}/favorite" />
  <APICall
    id="unfavoritePost"
    method="post"
    url="/api/posts/{$param}/unfavorite" />
  <DataSource
    id="timelineData"
    url="/api/timeline"
    method="GET" />
  <VStack>
    <H3>Social Media Timeline</H3>
    <Items data="{timelineData}">
      <Card>
        <VStack>
          <H4>{$item.author}</H4>
          <Text>{$item.content}</Text>
          <HStack verticalAlignment="center">
            <HStack verticalAlignment="center">
              <SocialButton icon="reply" />
              <Text>{$item.replies_count}</Text>
            </HStack>
            <HStack verticalAlignment="center">
              <SocialButton icon="trending-up" />
              <Text>{$item.reblogs_count}</Text>
            </HStack>
            <HStack verticalAlignment="center">
              <SocialButton
                icon='like'
                themeColor="{$item.favourited ? 'attention' : 'secondary'}"
                onClick="() => {
                  if ($item.favourited) {
                    unfavoritePost.execute($item.id)
                    timelineData.refetch();
                  } else {
                    favoritePost.execute($item.id)
                    timelineData.refetch();
                  }
                }
                " />
              <Text variant="caption">{$item.favourites_count}</Text>
            </HStack>
          </HStack>
        </VStack>
      </Card>
    </Items>
  </VStack>
</App>

Key points

execute() returns a response from the backend: you can run code after the API call succeeds — such as refetching a DataSource, showing a toast, or navigating to another page.

refetch() re-issues the DataSource's request: Calling timelineData.refetch() re-sends the original query and updates every element bound to that DataSource when the fresh data arrives.

This pattern gives you surgical control: Unlike blanket cache invalidation (which refreshes every DataSource), ds.refetch() refreshes only the specific DataSource you choose.

Combine with invalidates="{[]}" to prevent double-fetching: By default a successful APICall invalidates all caches. If you manually refetch, set invalidates="{[]}" on the APICall to avoid a redundant second fetch.


See also