Пример 202: Ресурс с настройками "из коробки"
См. комментарии
tsx
import baseClasses from '~/ui.common.module.scss'
import btnClasses from '~/ui.button.module.scss'
import { AbstractService, ReactiveEngine, useReactiveValue } from '@pravosleva/reactive-engine'
import clsx from 'clsx'
const BASE_API_URL = import.meta.env.VITE_BASE_API_URL
class Logic extends AbstractService {
public counter = this.engine.signal<number>(0, 'example-202:signal:counter');
public doubledCounter = this.engine.computed<number>(() => this.counter.value * 2, 'example-202:computed:counter');
public apiState = this.engine.resource(
async (counterValue, abortSignal) => {
const res = await fetch(
[
`${BASE_API_URL}/profile/search-incorrect`,
'?',
[
`counter=${counterValue}`,
'_responseDelay=10000',
].join('&')
].join(''),
{ signal: abortSignal }
)
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`)
return res.json()
},
this.counter,
{
name: 'example-202:resource:exp-backoff-exp',
retryCount: 4, // Сделать до 4 повторов при ошибках сети
retryDelay: 1000, // Стартовая задержка 1 секунда
isExponentialBackoffEnabled: true, // Интервалы будут: ~1с -> ~2с -> ~4с -> ~8с
maxRetryDelay: 10000, // Рост остановится на 10 секундах! Попытки 4, 5 и 6 будут ждать ~10с
// Добавляем пре-валидацию входного сигнала на уровне настроек:
// Если возвращает строку, ядро автоматически запишет её в error, минуя fetch и ретраи
validateBeforeFetch: (counterValue) => {
if (counterValue === 0) {
return `Not started (pre-validation before fetch) for count value ${counterValue}`;
}
return true; // Валидация успешна, можно делать fetch
},
}
)
public inc() {
this.counter.value += 1
}
}
const engine = new ReactiveEngine()
export const Example202 = () => {
const logic = engine.inject(Logic)
const counter = engine.use(logic.counter)
const { loading, data, error, isRetrying } = useReactiveValue(logic.apiState)
return (
<div className={clsx(baseClasses.unit, baseClasses.stack2)}>
<div className={baseClasses.absoluteUnitLabel} title='Resource with exponential backoff support'>Resource with exponential backoff support</div>
<code>{BASE_API_URL}</code>
<div style={{ minWidth: '100%' }}>
<button onClick={() => logic.inc()} className={clsx(btnClasses.btn, btnClasses.neonBtn, btnClasses['neonBtn--primary'], btnClasses['neonBtn--outlined'])}>
({counter}) Refresh account data
</button>
</div>
<div style={{ display: 'flex', gap: '8px', flexDirection: 'row', flexWrap: 'wrap', alignItems: 'center' }}>
<span>{loading ? '🟡 loading...' : !!data ? '🟢 ok' : !!error ? '🔴 err' : '⚪'} | isRetrying: {String(isRetrying)}</span>
{!!error?.message && <em>{error?.message}</em>}
</div>
<pre className={baseClasses.preNormalizedMin}>{JSON.stringify({ data }, null, 2)}</pre>
</div>
)
}