effector
effector copied to clipboard
Simplify handling of multiple derived effects
Proposal
Know for me it's too hard to handle multiple derived effects. Patronum has pending() but it doesnt help a lot:
const $processing = pending({ effects: [loadFirst, loadSecond] });
export const $message = createStore('');
export const helloFx = createEffect(async () => {
return new Promise(resolve => setTimeout(() => resolve('hello'), 3000))
})
export const byeFx = createEffect(async () => {
return new Promise(resolve => setTimeout(() => resolve('bye'), 500))
})
const changeEvent = createEvent() // changeEvent triggers someFx3
const $processing = patronum.pending({
effects: [helloFx, byeFx],
})
sample({
clock: changeEvent,
target: [helloFx, byeFx],
})
//now what if i need to construct store from fetched data?
// i can do this? No, becase it runs each time separately
sample({
clock: [helloFx.doneData, byeFx.doneData],
source: $processing,
fn: (processing, data) => {
},
target: $message,
})
// i can construct it like that, but it's too hard to handle.
$message.on(helloFx.doneData, (message, data) => {
if(message != '') {
return `${data}${message}`
} else {
return `${data}_`;
}
});
$message.on(byeFx.doneData, (message, data) => {
if(message != '') {
return `${message}${data}`
} else {
return `_${data}`;
}
})
// we can do this
// but it's a lot of work too, because we need to create two separate stores for data.
const $helloRes = createStore('');
const $byeRes = createStore('');
$helloRes.on(helloFx.doneData, (_, data) => data);
$byeRes.on(byeFx.doneData, (_, data) => data);
const $new_message = combine($helloRes, $byeRes, (hello, bye) => `${hello}_${bye}`);
//okay, let's say that it's good. What if I want now to get new byeFx with different query params and use it in another store.
const anotherEvent = createEvent();
forward({
from: anotherEvent,
to: byeFx,
});
anotherEvent();
//know all units and samples that depends on byeFx will be called and my app will be crashed.
//we can solve issue with attach. Moreover, attach is not for creating copy of Fx semantically its for passing data from stores.
const byeCopy1Fx = attach({
effect: byeFx,
mapParams: params => params,
})
const byeCopy2Fx = attach({
effect: byeFx,
mapParams: params => params,
})
//then we need to fix our code
const $helloRes = createStore('');
const $byeRes = createStore('');
const $someCoolStore = createStore('');
$helloRes.on(helloFx.doneData, (_, data) => data);
$byeRes.on(byeCopy1Fx.doneData, (_, data) => data);
$someCoolStore.on(byeCopy2Fx.doneData, (_, data) => data);
const $new_message = combine($helloRes, $byeRes, (hello, bye) => `${hello}_${bye}`);
const anotherEvent = createEvent();
forward({
from: anotherEvent,
to: byeCopy2Fx,
});
forward({
from: changeEvent,
to: [helloFx, byeCopy1Fx],
});
someEvent();
anotherEvent();
Can we somehow simplify work with multiple effects?
Use case
Know I found that we can use createEffect for effect copies:
myFx = createEffect(myBaseFx)
All the same overall process for me looks complicated
Looks like you need to use restore and attach with function and without mapParams:
const helloFx = createEffect(async () => {
return new Promise(resolve => setTimeout(() => resolve('hello'), 3000))
})
const byeFx = createEffect(async () => {
return new Promise(resolve => setTimeout(() => resolve('bye'), 500))
})
const $processing = patronum.pending({
effects: [helloFx, byeFx],
})
//we can solve issue with attach. Moreover, attach without mapParams is for creating copy of Fx semantically
/* admins.js */
const sayByeAdmins = createEvent()
const byeAdminsFx = attach({effect: byeFx})
const $adminsMessage = restore(byeAdminsFx, '')
forward({
from: sayByeAdmins,
to: byeAdminsFx,
})
/* users.js */
const byeUsersFx = attach({effect: byeFx})
const sayHelloByeUsers = createEvent()
const helloByeUsersFx = attach({
source: $processing,
async effect(source, params) {
const [hello, bye] = await Promise.all([
helloFx(),
byeUsersFx(),
])
return `${hello}_${bye}`
}
})
const $helloByeUsersMessage = restore(helloByeUsersFx, '')
sample({
clock: sayHelloByeUsers,
target: helloByeUsersFx,
})
/* app.js */
sayHelloByeUsers()
sayByeAdmins()
I wrote about attach with effect function recently
I need to think about it. thank you.