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
- 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.
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
useMemo false
Platform
.
Additional context
No response
Source: solidjs/solid