21. Tests are still complecated
We have some mess in components
etc...
function() {
updateSearchPage()({dispatch, getState: buildState(), api, cookie});
expect(dispatch.calledOnce).to.be.true;
expect(calledWithActions(
dispatch.getCall(0).args,
APPLIED_FILTERS_CHANGED,
GET_NOTICES_SUCCESS
)).to.be.true;
};
function onHandlePress () {
this.props.dispatch({type: 'SHOW_WAITING_MODAL'})
this.props.dispatch(createRequest())
}
REDUX-SAGA
22. The most elegant way to write complecated action creators
Look at this beautiful code
export function* authFlow() {
while(true) {
yield take(USER_AUTH_CHECK);
yield fork(authenticate);
const {user, token} = yield take(USER_AUTH_SUCCESS);
Session.save(user, auth);
yield put(redirectTo('/'));
const action = yield take(USER_SIGN_OUT);
Session.clear();
yield put(redirectTo('/'));
}
}
25. Generators are Functions with bene ts.
function* idMaker(){
var index = 0;
while(true)
yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
26. co - generator based control ow
var fn = co.wrap(function* (val) {
return yield Promise.resolve(val);
});
fn(true).then(function (val) {
});
28. Simple example What happens
here?
select part of the state
call the api method
put an action
export function* checkout() {
try {
const cart = yield select(getCart);
yield call(api.buyProducts, cart);
yield put(actions.checkoutSuccess(cart));
} catch(error) {
yield put(actions.checkoutFailure(error));
}
}
29. Easy to test
test('checkout Saga test', function (t) {
const generator = checkout()
let next = generator.next()
t.deepEqual(next.value, select(getCart),
"must select getCart"
)
next = generator.next(cart)
t.deepEqual(next.value, call(api.buyProducts, cart),
"must call api.buyProducts(cart)"
)
next = generator.next()
t.deepEqual(next.value, put(actions.checkoutSuccess(cart)),
"must yield actions.checkoutSuccess(cart)"
)
t.end()
})
34. can be useful to handle AJAX requests where we
want to only have the response to the latest request.
takeLatest
function* takeLatest(pattern, saga, ...args) {
let lastTask
while(true) {
const action = yield take(pattern)
if(lastTask)
// cancel is no-op if the task has alerady terminated
yield cancel(lastTask)
lastTask = yield fork(saga, ...args.concat(action))
}
}
35. allows multiple saga tasks to be forked
concurrently.
takeEvery
function* takeEvery(pattern, saga, ...args) {
while (true) {
const action = yield take(pattern)
yield fork(saga, ...args.concat(action))
}
}