#3524·solid

2.0.0-rc8 | `<Loading>` fallback reset does not detect changes when a signal source is pending , but does when it is from a memo

Author: mizuluCreated Sep 17, 2026Updated Sep 17, 2026

Describe the bug

  1. run repro with useMemo set to true toggle the button, see that the Loading?... is rendered

run repro with useMemo false click the button to toggle, see that Loading?... is not rendered instead we get stale data rendered.

typescript
import { render } from '@solidjs/web';
import { createSignal, createMemo, action, refresh, onSettled, Show, Loading } from 'solid-js';
import { createPersistingOptimistic } from "./solid2"



// update fetch id on interval 
let id = 0;
setInterval(() => {
  id++
}, 1000)

// fetch the data for current id 
const fetchData = async () => {
  await new Promise(r => setTimeout(r, 3000))
  return <>{"data" + id}</>
}


// wrap data in signal
const [data, setData] = createSignal(() => {
  return fetchData()
})

const [change, setChange] = createSignal(0)



var change2, setChange2;


// when useMemo is true. and toggling the component to Show
// we will see the "Loading?..."
// however if we use a signal instead. the loading does not trigger 
// when the change() dependency updates. 



let useMemo = true;
// let useMemo = false


if (useMemo) {
  change2 = createMemo(async () => {
    const c = change()
    await new Promise(r => setTimeout(r, 1000))
    return c
  })

} else {
  [change2, setChange2] = createSignal(async () => {
    const c = change()
    await new Promise(r => setTimeout(r, 1000))
    return c
  })

}


/**
 * When rendered will refresh data
 * - show loading until new data is resolved 
 */
function RefreshOnLoad() {
  const [loading, setLoading] = createPersistingOptimistic(true)

  // Action to trigger refresh and show loading affordance 
  const refreshData = action(async function* () {
    setLoading(true)
    refresh(data)
    setLoading(false)
  })

  // trigger the action on settled 
  onSettled(() => {
    refreshData()
    setChange(v => v + 1)
  })



  let i = 0 // used in on always return something different to always trigger fallback reset
  return <>
    {/**
    <div>
      {loading() ? "Loading" : data()}
    </div>
     */}

    <Loading on={(() => {
      // nothing reactive here will trigger fallback reset 
      // it must be triggered by a change inside the boundary.
      // simply returning a new value will always reset the fallback on 
      // any async dependency going into pending in the loading boundary.
      return i++;
    })()} fallback={<b>Loading?...</b>}>
      [{data()}]

      [{change2()}]
    </Loading>
  </>

}

export default function App() {
  const [toggle, setToggle] = createSignal(false);
  return (
    <Loading fallback={"initial loading"}>
      <div class="p-2">


        <div>
          {data()}
        </div>

        <div>
          <Show when={toggle()}>
            <RefreshOnLoad />
          </Show>
        </div>



        <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={() => setToggle(v => !v)}>
          Toggle: {toggle()}
        </button>
      </div >
    </Loading>
  );
}


if (typeof document !== 'undefined') {
  render(() => <App />, document.getElementById('root')!);
}



Your Example Website or App

https://s.olid.uk/id/WAvU6sKpQrKi3Gnkqdjj9A

Steps to Reproduce the Bug or Issue

see repro

Expected behavior

it is expected that memo or signal getter would trigger the fallback reset when the dependency changes and they should go into pending.

both memo and signal have an async source function with dependency on change() signal

Screenshots or Videos

useMemo true

Image

useMemo false

Image

Platform

.

Additional context

No response