Comments (18)
I'm pretty interested. Currently I'm using a plugin that I wrote to overwrite context.executeAction. I think it's mostly backwards compatible; I think the only case where it's not backwards compatible is when you're using the arguments object.
I've been abusing co and generators, so feel free to ignore that part. From my actions I could just export co.wrap(action) instead to achieve the same goal.
action-plugin.js
var co = require('co'),
debug = require('debug'),
log = debug('ActionPlugin'),
isPromise = require('is-promise'),
isGeneratorFunction = require('is-generator-function')
module.exports = function ActionPlugin () {
return {
name: 'ActionPlugin',
plugContext
}
}
function plugContext (opts, context) {
context.executeAction = executeAction.bind(context)
return {
plugComponentContext,
plugActionContext
}
function plugActionContext (actionContext) {
actionContext.executeAction = context.executeAction
}
function plugComponentContext (componentContext) {
componentContext.executeAction = componentContextAction
}
function componentContextAction (action, payload) {
context.executeAction(action, payload).catch(err => {
context.executeAction(context._app._componentActionHandler, {err}, () => {})
})
}
}
function executeAction (action, payload={}, done) {
log(`Executing action ${action.displayName || action.name} with payload ${payload}`)
var promise
if (isGeneratorFunction(action)) {
promise = co(action(this.getActionContext(), payload))
} else {
promise = new Promise((resolve, reject) => {
var result = action(this.getActionContext(), payload, (e, r) => e ? reject(e) : resolve(r))
if (isPromise(result)) {
result.then(resolve, reject)
} else if (action.length < 3) {
resolve(result)
}
})
}
if (done)
promise.then(result => done(null, result)).catch(err => done(err))
return promise
}
If it's a generator function, call the action with action context and payload, and pass it to co.
Otherwise call the action with action context, payload, and a callback inside of a promise. If a promise is returned then wait for that. If it has less than three params assume its sync, and resolve with the returned value. If the the action has 3 params then it will have received the callback, which will also resolve the promise. Finally, if the action has less than 3 params and it throws, I think the promise will catch it and it'll get rejected.
If execute action got called with a third param, it'll also call done. One of the nice perk of using promises is that you don't have to worry about releasing zalgo.
Would you be interested in a PR or did you have a different approach in mind?
from fluxible.
Yes, we'll absolutely take a PR.
I'm not a big fan of adding co
as a dependency though, so maybe we leave that part out for now.
from fluxible.
Oh, definitely. co
is too opinionated for something like this, I think just supporting promises is fine.
Should it use the global Promise and assume that anyone that's using this will either polyfill it or replace it with their own preferred implementation?
from fluxible.
Good question. For now let's use Bluebird. Once we start using babel to compile Fluxible for ES6, we will be able to drop that dependency.
from fluxible.
Hi @cesarandreu we've migrated the docs over to this repo so if you want to add some documentation we can get this merged.
from fluxible.
👍 👍 👍 👍 =)
from fluxible.
I'll try to write up the docs tonight, thanks! :D
from fluxible.
IMHO, having callbacks and/or promises in actions is breaking Flux unidirectional data flow. According to a Facebook developer post:
- Actions don't have callbacks, as they are by design fire-and-forget.
Why Fluxible did this "correction"?
from fluxible.
@igorbt your observation is correct. In order to render server-side, we need to know when the page is ready to render. And we do that with callbacks. However, we do keep the flux flow with actions fired from the componentContext
(from your React views)... those are still fire-and-forget (no callbacks).
from fluxible.
@igorbt There is a description of what @jedireza mentioned in the Components documentation.
from fluxible.
Thanks, @jedireza , @mridgway ! I understand now. It would be nice to see this explanation in the Actions documentation also.
Btw, is it legit to pass parameters in the action callback function then? I was tempted to do so, but if the only purpose of the callback is to know when to render, then it probably would be wrong.
from fluxible.
Haven't had a chance to update the docs yet.
@igorbt:
In my PR, the action promise will be resolved with the callback value e.g. done(null, value)
, the returned promise's resolve value e.g. return Promise.resolve(value)
, or if the action function has length below 3, it'll resolve the action promise with the returned value, e.g. return value
I think triggering actions inside of actions is fine as long as you make sure to wait for them in your parent action.
from fluxible.
@igorbt Good call out. I added more information to the actions doc.
from fluxible.
I'm just starting to explore Flux and Fluxible and the thing with calling another action from an action just doesn't feel right for me. I re-read the original Facebook Flux description but didn't find anything for or against this practice. I didn't find anywhere else some strong opinion about that.
If Action1 calls Action2 and then dispatch Payload1, and in the same time Action2 dispatches Payload2, if feels like cascading updates. But Flux is trying to minimize that!
The thing seems to me even worst when Action2 returns Payload2 as value (in callback or promise) and Action1 then uses Payload2 to construct Payload1. Then Payload1 is derived data. It seems more like a Store responsibility.
from fluxible.
While the actions may be asynchronous, there's nothing wrong with nearly-simultaneous dispatches--the stores should handle events and their payloads discretely, only being concerned with potentially waiting for other stores to handle an event first (using waitFor
).
This isn't cascading, only asynchronous. It would be cascading if the stores were to trigger an action, or a component doing so without any user interaction.
Does that clarify at all? (Disclaimer: I do not work on Fluxible)
from fluxible.
Furthermore, IMO it's very helpful for actions to set up other actions on intervals, for situations like polling.
from fluxible.
Updated my PR with docs!
from fluxible.
Awesome! I'll check it out soon.
from fluxible.
Related Issues (20)
- Support registering services that return promises HOT 4
- Some properties are not showing. HOT 1
- compatibility with React v16 HOT 4
- An in-range update of babel-eslint is breaking the build 🚨 HOT 3
- An in-range update of sinon is breaking the build 🚨 HOT 5
- [addons-react] Following React 16.3+ new Context API ? HOT 7
- componentWillReceiveProps to getDerivedStateFromProps HOT 5
- Version 10 of node.js has been released HOT 1
- [fluxible] context.executeAction(action, null, callback) invokes the callback before the async action finishes HOT 1
- An in-range update of react is breaking the build 🚨 HOT 2
- An in-range update of react is breaking the build 🚨 HOT 25
- Should dispatch NAVIGATE_FAILURE if action is not able to resolve HOT 2
- An in-range update of eslint-plugin-react is breaking the build 🚨 HOT 12
- Update React lifecycle methods HOT 2
- [fluxible-addons-react] react 16 task list HOT 26
- TypeError: this.props.currentRoute is null HOT 2
- Render a component when error occurs HOT 1
- Question regarding debug dependency HOT 6
- Update Access the context site docs
- useStore hook HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fluxible.