Skip to content

Instantly share code, notes, and snippets.

@artalar
Created July 8, 2023 16:10
Show Gist options
  • Save artalar/0a0f8d6043ad5cbe3e0d31828ee8f15b to your computer and use it in GitHub Desktop.
Save artalar/0a0f8d6043ad5cbe3e0d31828ee8f15b to your computer and use it in GitHub Desktop.
some effector VS reatom
import { $corsProxyEnabled } from '@/src/entities/cors-proxy/model/store'
import { checkInstanceUrl } from '@/src/features/instance/api/check'
import { InstanceCheckResult } from '@/src/features/instance/model/model'
import { BuildConfig } from '@/src/shared/model/build-config'
import {
combine,
createEffect,
createEvent,
createStore,
restore,
sample,
} from 'effector'
import { delay, snapshot, spread } from 'patronum'
export const instanceUrlChanged = createEvent<string>()
export const $instanceUrl = restore(
instanceUrlChanged,
BuildConfig.defaultInstanceUrl,
)
export const instanceCheckStarted = createEvent()
export const checkAndSaveInstanceFx = createEffect(checkInstanceUrl)
export const $checkResult = createStore<InstanceCheckResult | null>(null)
export const $checkError = restore(checkAndSaveInstanceFx.failData, null)
export const $editorShowOverlay = createStore(false)
export const editorOpened = createEvent()
export const editorCancelled = createEvent()
export const editorSaveStarted = createEvent()
export const editorSaveSucceeded = createEvent()
export const $editorEditing = createStore(false)
$editorEditing.on(editorOpened, () => true)
$editorEditing.on([editorCancelled, editorSaveSucceeded], () => false)
export const $beforeEditorSnapshot = snapshot({
source: combine({
url: $instanceUrl,
result: $checkResult,
error: $checkError,
}),
clock: editorOpened,
})
sample({
clock: editorOpened,
fn: () => null,
target: [$checkResult, $checkError],
})
sample({
source: $instanceUrl,
clock: [instanceCheckStarted, editorSaveStarted],
target: checkAndSaveInstanceFx,
})
sample({
clock: editorSaveStarted,
fn: () => true,
target: $editorShowOverlay,
})
sample({
source: $corsProxyEnabled,
clock: checkAndSaveInstanceFx.doneData,
fn: (corsEnabled, data) => {
if (corsEnabled || !data.cors) {
return { ok: data }
}
return {
error: new Error('This instance requires the use of CORS Proxy'),
}
},
target: spread({
targets: {
ok: $checkResult,
error: $checkError,
},
}),
})
const editorCheckSucceeded = sample({
source: $editorEditing,
clock: $checkResult,
filter: (editing, result) => result !== null && editing,
})
sample({
clock: delay({
source: editorCheckSucceeded,
timeout: 2500,
}),
target: editorSaveSucceeded,
})
const editorCheckErrored = sample({
source: $editorEditing,
clock: $checkError,
filter: (editing, error) => error !== null && editing,
})
sample({
clock: delay({
source: editorCheckErrored,
timeout: 2500,
}),
fn: () => ({
null: null,
false: false,
}),
target: spread({
targets: {
null: $checkError,
false: $editorShowOverlay,
},
}),
})
sample({
clock: [editorCancelled, editorSaveSucceeded],
fn: () => false,
target: $editorShowOverlay,
})
sample({
clock: editorCancelled,
source: $beforeEditorSnapshot,
target: spread({
targets: {
url: $instanceUrl,
error: $checkError,
result: $checkResult,
},
}),
})
import { corsProxyEnabledAtom } from '@/src/entities/cors-proxy/model/store'
import { checkInstanceUrl } from '@/src/features/instance/api/check'
import { InstanceCheckResult } from '@/src/features/instance/model/model'
import { BuildConfig } from '@/src/shared/model/build-config'
import {
action,
atom,
reatomAsync,
sleep,
withDataAtom,
withErrorAtom,
} from '@reatom/framework'
export const instanceUrlAtom = atom(
BuildConfig.defaultInstanceUrl,
'instanceUrlAtom',
)
export const editorShowOverlayAtom = atom(false, 'editorShowOverlayAtom')
export const editorEditingAtom = atom(false, 'editorEditingAtom')
export const beforeEditorSnapshotAtom = atom(
{
url: '',
result: null as null | InstanceCheckResult,
error: undefined as undefined | Error,
},
'beforeEditorSnapshotAtom',
)
export const checkAndSaveInstance = reatomAsync(async (ctx) => {
const corsEnabled = ctx.get(corsProxyEnabledAtom)
const data = await checkInstanceUrl(ctx.get(instanceUrlAtom))
if (corsEnabled || !data.cors) return data
throw new Error('This instance requires the use of CORS Proxy')
}, 'checkAndSaveInstance').pipe(withDataAtom(null), withErrorAtom())
export const instanceCheckStarted = action((ctx) => {
checkAndSaveInstance(ctx)
}, 'instanceCheckStarted')
export const editorOpened = action((ctx) => {
editorEditingAtom(ctx, true)
beforeEditorSnapshotAtom(ctx, {
url: ctx.get(instanceUrlAtom),
result: ctx.get(checkAndSaveInstance.dataAtom),
error: ctx.get(checkAndSaveInstance.errorAtom),
})
checkAndSaveInstance.dataAtom.reset(ctx)
checkAndSaveInstance.errorAtom.reset(ctx)
}, 'editorOpened')
export const editorCancelled = action((ctx) => {
editorEditingAtom(ctx, false)
editorShowOverlayAtom(ctx, false)
const { url, result, error } = ctx.get(beforeEditorSnapshotAtom)
instanceUrlAtom(ctx, url)
checkAndSaveInstance.dataAtom(ctx, result)
checkAndSaveInstance.errorAtom(ctx, error)
}, 'editorCancelled')
export const editorSaveStarted = action((ctx) => {
editorShowOverlayAtom(ctx, true)
checkAndSaveInstance(ctx)
}, 'editorSaveStarted')
export const editorSaveSucceeded = action((ctx) => {
editorEditingAtom(ctx, false)
editorShowOverlayAtom(ctx, false)
}, 'editorSaveSucceeded')
checkAndSaveInstance.dataAtom.onChange(async (ctx, result) => {
const editorEditing = ctx.get(editorEditingAtom)
if (result !== null && editorEditing) {
await ctx.schedule(async () => await sleep(2500))
editorSaveSucceeded(ctx)
}
})
checkAndSaveInstance.errorAtom.onChange(async (ctx, error) => {
const editorEditing = ctx.get(editorEditingAtom)
if (error !== null && editorEditing) {
await ctx.schedule(async () => await sleep(2500))
checkAndSaveInstance.errorAtom.reset(ctx)
editorShowOverlayAtom(ctx, false)
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment