fix(core): reading resource value after reload in the error state (#61441)

When the resource is loading after reloading from the error state reading `Resource.value()` would return the default value instead of throwing an error.
This change prevents `Resource.hasValue()` from throwing an error in such a case.

PR Close #61441
This commit is contained in:
Maciej Sawicki
2025-04-30 12:02:03 +02:00
committed by Andrew Scott
parent 3ba39bc28f
commit 6e79eaf739
2 changed files with 47 additions and 0 deletions
+5
View File
@@ -187,6 +187,11 @@ export class ResourceImpl<T, R> extends BaseWritableResource<T> implements Resou
return defaultValue;
}
// Prevents `hasValue()` from throwing an error when a reload happened in the error state
if (this.state().status === 'loading' && this.error()) {
return defaultValue;
}
if (!isResolved(streamValue)) {
if (throwErrorsFromValue) {
throw new ResourceValueError(this.error()!);
@@ -835,6 +835,48 @@ describe('resource', () => {
expect(echoResource.error()).toBe(undefined);
expect(aborted).toEqual([{counter: 0}, {counter: 0}]);
});
it('should return default value when getting a value after reloading in the error state', async () => {
const backend = new MockEchoBackend();
const requestParam = {};
const echoResource = resource({
params: () => requestParam,
loader: (params) => backend.fetch(params.params),
injector: TestBed.inject(Injector),
defaultValue: 'my-default-value',
});
TestBed.tick();
await backend.reject(requestParam, new Error('Something went wrong....'));
expect(echoResource.status()).toBe('error');
expect(echoResource.isLoading()).toBeFalse();
expect(echoResource.hasValue()).toBeFalse();
const errFromValue = extractError(() => echoResource.value())!;
expect(errFromValue.message).toContain('Resource');
expect(errFromValue.message).toContain('Something went wrong....');
expect(errFromValue.cause).toEqual(new Error('Something went wrong....'));
expect(echoResource.error()!).toEqual(new Error('Something went wrong....'));
echoResource.reload();
TestBed.tick();
expect(echoResource.status()).toBe('reloading');
expect(echoResource.isLoading()).toBeTrue();
expect(echoResource.hasValue()).toBeTrue();
expect(echoResource.value()).toEqual('my-default-value');
expect(echoResource.error()).toEqual(new Error('Something went wrong....'));
await backend.flush();
TestBed.tick();
expect(echoResource.status()).toBe('resolved');
expect(echoResource.isLoading()).toBeFalse();
expect(echoResource.hasValue()).toBeTrue();
expect(echoResource.value()).toEqual({});
expect(echoResource.error()).toEqual(undefined);
});
});
function flushMicrotasks(): Promise<void> {