question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Effects with Sagas & Subscriptions

See original GitHub issue

First of all, I’d just like to say I like a lot of the design decisions in Mirror.js. Great work, with many improvements over DVA. I’ll continue writing with an assumption that you may be familiar with DVAs API.

I have two suggestions that I would like to help create to bring both sagas with effects & an improved form of subscriptions to mirror.js. I believe this can be done without adding much additional weight to mirror.js.

1. Effects using Sagas

One feature that remains missing is effects that run as sagas.

Using Mirror, sagas can still be used, but not within effects (as they are not running sagas).

I’m not at all suggesting copying the way effects are done in DVA. In DVA saga effects are passed in as the second param.

  // within dva model
  effects: {
    *someEffect(action, effects) {
      effects.put({ type: 'someAction' })
    }
  }

This isn’t really necessary, since saga effects can be imported.

Note that I’m also not suggesting that redux-saga should become a dependency of mirror.js.

2. Subscriptions

In DVA, subscriptions run within a model on startup. These can be used to load data on startup of a model, among other uses.

When using sagas, it would be more effective if you could launch saga watchers on startup. Watchers are generator functions that allow you to create action listeners that trigger other functions. They can really help to keep your models from entangling each other with calls.

This is a two step process in DVA, (subscription calls an effect, effect calls a watcher). In DVA subscriptions are not sagas, but I would like to be able to overwrite how subscriptions work to make them into sagas as well.

// within dva model
subscriptions: {
  *watch() {
    // pause until a user is logged in
    yield take('authenticated')
    // listen for an action, and trigger an effect
    yield takeEvery('someAction', put({ type: 'doSomething' })
  }
}

This would create a very elegant and clear way to use sagas within a model.

Subscriptions could made to check if the function is a generator or not. Generators could run using a saga, whereas functions could run as normal.

Proposal

What I would like to do is be able to overwrite how effects are handled as a default option. I’d also like to add subscriptions with an optional overwrite.

For example:

mirror.defaults({
  effects: customEffectsHandler, // overwrite existing function
  subscriptions: customSubscriptionHandler, // create additional function that runs on startup
  middlewares: [sagaMiddleware],
})

I’d be happy to put in a PR for review, as well as to publish and maintain a mirror-saga module separately.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
ShMcKcommented, Sep 6, 2017

I’ve created one more PR to clean up a blocking issue in the previous PR. #43

I’ve also created a separate package which contains Mirror-Saga, a plugin for adding sagas.

Setup

import mirrorSaga from 'mirror-saga'

mirror.defaults(mirrorSaga())

// OR optionally pass in mirror default options
// mirror.defaults(mirrorSaga(options))

Example

Add model effects as generators (*function) and they will be treated as sagas by middleware.

mirror.model({
  name: 'app',
  // ...
  effects: {
    *runASaga(payload) {
      yield delay(1000)
      yield actions.app.doSomething(payload)
    },
  }
})

Effects that are not generators will run normally.

export default {
  name: 'app',
  effects: {
    // runs as async function
    async incrementAsync() {
      await asyncDelay(1000)
      actions.app.increment()
    },
    // runs as saga
    *incrementAsyncSaga() {
      yield delay(1000)
      yield actions.app.increment()
    },
  }
}
1reaction
llh911001commented, Sep 1, 2017

Yes, #37 was merged!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Declarative Effects | Redux-Saga
To express the Saga logic, we yield plain JavaScript Objects from the Generator. We call those Objects Effects. An Effect is an object...
Read more >
Asynchronous with Redux Sagas - Medium
Sagas, similar to normal reducers, are functions which listen for dispatched actions, perform side effects, and return their own actions ...
Read more >
Understanding Redux Saga: From action creators to sagas
Learn how to use Redux Saga for both simple and complex approaches to implementing async operations with action creators, thunks, and sagas.
Read more >
Handling Side Effects in Redux: Redux-Saga - Soshace
Effects are divided into two groups in redux-saga, blocking call and non-blocking call. A blocking call means that the saga yielded an effect...
Read more >
NgRx Sagas - DEV Community ‍ ‍
But that's just the way it is, right? Well, perhaps not. The redux-saga project provides an interesting alternative way of writing side effects...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found