React Meetup Düsseldorf
[…] a Saga is like a separate thread in your application that's solely responsible for side effects.
function* generator() { /* ... */ }
const iterator = generator() // => Object
iterator.next() => { value: T | undefined, done: bool }
for (const item of iterator) { // calls iterator.next()
console.log(item)
}
function* generator() {
const num = 2
// Pass value to callee and pause execution
yield 1
}
const iterator = generator()
function* generator() {
const num = 2
// Pass value to callee and pause execution
yield 1
}
const iterator = generator()
// Generator progress controlled from outside
iterator.next().value == 1
function* generator() {
const num = 2
// Pass value to callee and pause execution
yield 1
// Callee can pass values into generator
let a = yield 2
}
const iterator = generator()
// Generator progress controlled from outside
iterator.next().value == 1
iterator.next().value == 2
function* generator() {
const num = 2
// Pass value to callee and pause execution
yield 1
// Callee can pass values into generator
let a = yield 2
// `num` maintains value across yield points
yield a + num
}
const iterator = generator()
// Generator progress controlled from outside
iterator.next().value == 1
iterator.next().value == 2
iterator.next(10).value == 12
function* generator() {
const num = 2
// Pass value to callee and pause execution
yield 1
// Callee can pass values into generator
let a = yield 2
// `num` maintains value across yield points
yield a + num
}
const iterator = generator()
// Generator progress controlled from outside
iterator.next().value == 1
iterator.next().value == 2
iterator.next(10).value == 12
iterator.next().done == true
function* saga() {
yield put({
type: "SET_JOKE",
payload: "What do you call a fake noodle? An impasta!",
})
}
saga().next() == {
PUT: {
action: {
type: "SET_JOKE",
payload: "What do you call a fake noodle? An impasta!",
}
}
}
function* fetchJoke() {
const { joke } = yield call(
fetchJson,
"https://icanhazdadjoke.com/",
)
yield put({ type: 'SET_JOKE', payload: joke })
}
function* jokeThread() {
while (true) {
const action = yield take('GET_JOKE')
yield fork(fetchJoke)
}
}
App Lifecycle
Login → Interaction → Logout → Login …
function* app() {
while (true) {
yield waitForlogin()
const pid = yield fork(runDataFetching)
yield waitForLogout()
yield cancel(pid)
}
}
it("should fetch a joke and store it in the state", () => {
const jokeMock = {
joke: "Chuck Norris knows the last digit of pi."
}
const it = fetchJoke()
})
it("should fetch a joke and store it in the state", () => {
const jokeMock = {
joke: "Chuck Norris knows the last digit of pi."
}
const it = fetchJoke()
it.next() // returns { CALL: { ... } } effect object
})
it("should fetch a joke and store it in the state", () => {
const jokeMock = {
joke: "Chuck Norris knows the last digit of pi."
}
const it = fetchJoke()
it.next() // returns { CALL: { ... } } effect object
expect(it.next(jokeMock).value).toEqual(put({
type: "SET_JOKE",
payload: jokeMock.joke,
}))
})
it("should fetch a joke and store it in the state", () => {
const jokeMock = {
joke: "Chuck Norris knows the last digit of pi."
}
const it = fetchJoke()
it.next() // returns { CALL: { ... } } effect object
expect(it.next(jokeMock).value).toEqual(put({
type: "SET_JOKE",
payload: jokeMock.joke,
}))
expect(it.next())
.toEqual({ done: true, value: undefined })
})
function* handleInput({ payload }) {
yield delay(500)
const res = yield call(
fetch,
"https://myAPI",
{ body: payload },
)
}
function* watchInput() {
yield takeLatest('INPUT_CHANGED', handleInput)
}
function* request() {
while (true) {
const res = yield call(fetch, "https://myAPI")
if (res) {
put(...)
return
}
yield delay(5000)
}
}
const io = {
dispatch(action) => /* saga dispatches an action */,
getState() => /* saga requests app state */,
subscribe(callback) => /* on action: callback(action) */,
}
runSaga(io, saga)