Guys and Girls,
i'm just digging into redux-saga, and i'm stuck on this Usecase. Maybe Sagas aren't the right solution for this problem, but i want to use them anyway because the whole app is build around them.
Let's say i am dispatching an action on user click on a button:
{ type: COUNT_UP, count: 1 }
Now i want to count the number up in an reducer, but i also want to keep track of the counts the user does, and dispatch another action containing all the past counts once the user stopped clicking for let's say 5 seconds. Let's say the user counted 10 times.
{type: USER_COUNTED, count: 10}
So, whats the best way to do this via Sagas, i tried to approach this via delays, Channels and much more stuff. The only way i found is calling a custom setTimeout within a promise, which sets the timeout to a global and clears it when a new count action comes in. But that doesn't seem to be right.
let to
function* sleep(time) {
yield new Promise(resolve => {
to = setTimeout(resolve, time)
})
}
function* clear() {
yield new Promise(resolve => {
clearTimeout(to)
resolve()
})
}
export function* incrementAsync() {
yield call(clear)
yield call(sleep, 3000)
yield put({ type: 'USER_COUNTED' })
}
export function* watchIncrementAsync() {
yield takeEvery('COUNT_UP', incrementAsync)
}
Am i completely wrong here?
Philip Davis
Software developer
Ok, we have another solution now, which looks more promising.
let cacheIncrement = 0
let cacheLastIncrement = 0
export function* incrementAsync({ payload, time }) {
cacheIncrement += 1
cacheLastIncrement = time
yield call(delay, 5000)
const diff = (new Date().getTime() / 1000) - cacheLastIncrement
if (diff >= 5 && cacheIncrement > 0) {
yield put({ type: 'USER_COUNTED', value: cacheIncrement })
cacheIncrement = 0
}
}
export function* watchIncrementAsync() {
yield takeEvery('COUNT_UP', incrementAsync)
}
export function *incrementSaga() { let counter; while (true) { yield take('COUNT_UP'); counter = 1; while (true) { const { inc } = yield race({ inc: take('COUNT_UP'), timeout: call(delay, 5000), }); if (inc) { counter++; } else { yield put({ type: 'USER_COUNTED', value: counter }); break; } } } }More here