GithubHelp home page GithubHelp logo

flux's Introduction

⚠️ The Flux project is in maintenance mode and there are many more sophisticated alternatives available (e.g. Redux, MobX, or Recoil) and we would recommend using them instead.

logo

Flux

An application architecture for React utilizing a unidirectional data flow.
Licence Badge Current npm package version.


Getting Started

Start by looking through the guides and examples on Github. For more resources and API docs check out facebook.github.io/flux.

How Flux works

For more information on how Flux works check out the Flux Concepts guide, or the In Depth Overview.

Requirements

Flux is more of a pattern than a framework, and does not have any hard dependencies. However, we often use EventEmitter as a basis for Stores and React for our Views. The one piece of Flux not readily available elsewhere is the Dispatcher. This module, along with some other utilities, is available here to complete your Flux toolbox.

Installing Flux

Flux is available as a npm module, so you can add it to your package.json file or run npm install flux. The dispatcher will be available as Flux.Dispatcher and can be required like this:

const Dispatcher = require('flux').Dispatcher;

Take a look at the dispatcher API and some examples.

Flux Utils

We have also provided some basic utility classes to help get you started with Flux. These base classes are a solid foundation for a simple Flux application, but they are not a feature-complete framework that will handle all use cases. There are many other great Flux frameworks out there if these utilities do not fulfill your needs.

import {ReduceStore} from 'flux/utils';

class CounterStore extends ReduceStore<number> {
  getInitialState(): number {
    return 0;
  }

  reduce(state: number, action: Object): number {
    switch (action.type) {
      case 'increment':
        return state + 1;

      case 'square':
        return state * state;

      default:
        return state;
    }
  }
}

Check out the examples and documentation for more information.

Building Flux from a Cloned Repo

Clone the repo and navigate into the resulting flux directory. Then run npm install.

This will run Gulp-based build tasks automatically and produce the file Flux.js, which you can then require as a module.

You could then require the Dispatcher like so:

const Dispatcher = require('path/to/this/directory/Flux').Dispatcher;

The build process also produces de-sugared versions of the Dispatcher and invariant modules in a lib directory, and you can require those modules directly, copying them into whatever directory is most convenient for you. The flux-todomvc and flux-chat example applications both do this.

Join the Flux community

See the CONTRIBUTING file for how to help out.

License

Flux is BSD-licensed. We also provide an additional patent grant.

flux's People

Contributors

adithyaakrishna avatar alexeyraspopov avatar alexkval avatar chikamichi avatar cuth avatar dependabot[bot] avatar dmitryvinn avatar dschaller avatar fisherwebdev avatar flarnie avatar guyellis avatar harrissavalon avatar haruair avatar jackcallister avatar jim-y avatar jingc avatar justinwoo avatar kassens avatar koba04 avatar kyldvs avatar lyip1992 avatar mikecousins avatar pieterv avatar rickbeerendonk avatar rileytomasek avatar sophiebits avatar vjeux avatar yangshun avatar zertosh avatar zpao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flux's Issues

[Question] store.getItem() which may require an async server call

Hi. I want to discuss the best practice for a situation where data will be lazily fetched and if the way I'm currently doing it is a good way to do it.

  1. view calls store.getItem(123)
  2. store realize it haven't loaded item 123
  3. store sets loading = true
  4. store calls API.LoadItem({id:123})
  5. store emits that it has changed (due to loading = true)
  6. store returns null
  7. view handles null result
  8. view receives change event and can show user that store is loading
  9. [Async at 4] API.LoadItem fires ajax request. When request is resolved, fires Actions.ItemLoaded({result: ...})
  10. store receives callback on ItemLoaded, stores the result, sets loading to false and emit that it has changed.
  11. view receives change event, and updates it state, effetively recalling store.getItem(123).

Is this the proper way to solve such problem? I can see one issue above, which is number 6 & 7, because if getItem returns null, the view don't know if the resource doesn't exist or if it's pending. Would it be wise to wrap all get-calls with a status wrapper that could tell if we know for sure that 123 doesn't exist (we already tried ajax request and it failed) or if we just have to fire an request before we have the result.

Provide a base Store

I think it's kind of silly that clients of this module still have to write the same boilerplate for their stores. I think it'd be nice to provide a base for clients.

The simplest way to do this would be to do something like this:

var EventEmitter = require('events').EventEmitter;
var assign = require('react/lib/Object.assign');
var CHANGE_EVENT = 'change';

var Store = assign({}, EventEmitter.prototype, {
  emitChange: function() {
    this.emit(CHANGE_EVENT);
  },

  /**
   * @param {function} callback
   */
  addChangeListener: function(callback) {
    this.on(CHANGE_EVENT, callback);
  },

  /**
   * @param {function} callback
   */
  removeChangeListener: function(callback) {
    this.removeListener(CHANGE_EVENT, callback);
  }
});

module.exports = Store;

For even better usability, a constructing function could be provided:

function createStore(dispatcherCallback, methods) {
  return assign({}, BaseStore, methods, {
    dispatcherIndex: Dispatcher.register(dispatcherCallback)
  });
}

Here's an 'example' of how I think it could be done/used: https://github.com/justinwoo/15-puzzle/blob/c600e4d82344b2aa0ccf6c83e06c47a76e2431f7/src/Store.js#L114

Thoughts? Are people's implementations of stores much too different to handle something like this?

[Question] naming action

I'd like to discuss best practices about naming actions. Currently I use actions named after what user has done, for example 'FILE_CLICKED', 'ZOOMED', 'VIEW_MODE_BUTTON_CLICKED' etc, is that good convention to name action like that? Only issue I see so far is that I have many *._CLICKED actions. Some people also tend to name actions more like commands, for example 'LOAD_DOCUMENT', 'CHANGE_VIEW_MODE' etc. I'd love your thoughts on that.

Circular Dependencies between Stores

The current flux-chat example has a bug that means it doesn't update the lastMessage object in the ThreadStore. Trying to reconcile this by waiting for the MessageStore to complete (and then request the message list from the store) creates a circular dependency between MessageStore and ThreadStore.

I've ended up fixing this by doing the following:

  • Making a shared "DispatchTokens" object so one store can wait for another without requiring it as a dependency
  • Adding the full message object to payload.action (which otherwise only stores the text of the message)
  • Having the ThreadStore listen to the CREATE_MESSAGE action, wait for the MessageStore to complete, and updating lastMessage with the message object on the payload.

I'm curious if modifying the payload is the appropriate way of fixing this kind of issue. It seems like a viable option given that the waitFor guarantees that the message callback has completed, but does require a different way of storing dispatch tokens.

The other solution I had was to simply require MessageStore inside the ThreadStore callback instead of at the top of the file, but this felt a bit hacky.

Is mutating the payload considered an acceptable way of resolving this between stores, or is there a more 'Fluxy' way of doing things?

Flux Chat Example

I've noticed that both child components (Sections) are listening to the stores directly while saving the data as state (and not props). This seems a bit counter intuitive to me because:

  1. I would have expected the stores to be the only source of "truth", by storing their data as state in multiple components I can theoretically have colliding data.
  2. I also assumed that stores will be connected to the top most component and passed down as props.

Is this just an oversight? Or am I missing something here?

Why is it not possible to "dispatch in the middle of a dispatch"

Is there any reason why the dispatcher can't handle a dispatch in the middle of a dispatch?

I can't be sure, that this will not happen. I have a lot of async API calls that will dispatch events simultaneously and i'm running into this error.

Am i doing s.th. wrong? Is there any reason why you should not have a queue in the dispatcher?

Call setState onBlur stops event propagation, necessary to use window.setTimeout? or Bug in Flux?

I have an callback for onBlur that will setState, and based on the state, some buttons may be removed from the screen.

The problem is that one of these buttons has a callback that needs to run, and if setState is called from the onBlur callback, then the callback for the button does not run, probably because it's not technically visible. I verified that the button callback works fine if the onBlur callback does not call setState.

I worked around the issue by using a window.setTimout that calls setState after 250ms.

  • Is this the right approach?
  • Or is this a bug in flux that all callbacks don't run?

My expectation is that the all callbacks would run and the setState calls would be cummulative.

Thanks for any advice.

Logic inside actions

From Flux Overview, we have these statements:

  1. Stores contain the application state and logic.
  2. The actions are simply discrete, semantic helper functions that facilitate passing data to the dispatcher.

That said:

https://github.com/facebook/flux/blob/master/examples/flux-chat/js/actions/ChatMessageActionCreators.js

var message = MessageStore.getCreatedMessageData(text);
    ChatWebAPIUtils.createMessage(message);

I think that this logic should be placed inside the MessageStore:

https://github.com/facebook/flux/blob/master/examples/flux-chat/js/stores/MessageStore.js

case ActionTypes.CREATE_MESSAGE:
      var message = MessageStore.getCreatedMessageData(action.text);
      _messages[message.id] = message;
      /* HERE we call an async request, but don't wait for a response
          ChatWebAPIUtils.createMessage would trigger an error/success action */
      ChatWebAPIUtils.createMessage(message);
      MessageStore.emitChange();
      break;

Business logic is not responsibility of actions. Actions are just simple semantic helpers, while stores contain the application state and logic.

What do you think about?

npm install is ok,but npm start get erros

So I can't get a corect bundle.js. Maybe the reason is Windows 8.1?

npm ERR! [email protected] start: STATIC_ROOT=./static watchify -o js/bundle. s -v -d .
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is most likely a problem with the todomvc-flux package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! STATIC_ROOT=./static watchify -o js/bundle.js -v -d .
npm ERR! You can get their info via:
npm ERR! npm owner ls todomvc-flux
npm ERR! There is likely additional logging output above.
npm ERR! System Windows_NT 6.2.9200
npm ERR! command "d:\Program Files\nodejs\node.exe" "d:\Program Files\node
s\node_modules\npm\bin\npm-cli.js" "start"
npm ERR! cwd d:\web_try\flux\examples\flux-todomvc
npm ERR! node -v v0.10.31
npm ERR! npm -v 1.4.23
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! d:\web_try\flux\examples\flux-todomvc\npm-debug.log
npm ERR! not ok code 0

Flux Inspector ?

Are there any plans to create a flux inspector?

Something analogous to the React Dev tools or Ember Inspector.

I imagine any of these would be useful:

  1. List of all registered actions, with the ability to trigger them
  2. For a given action, show a list of stores that subscribe to it
  3. List of all stores and their current data
  4. For a given store, show a list of subscribed React Views.
  5. Show dependency tree of waitFor()'s

There are probably plenty of other snazzy things it could do that would help with prototyping and debugging.

Differences in object construction

Any information on why the difference between:

var TodoStore = merge(EventEmitter.prototype, {

and

var AppDispatcher = copyProperties(new Dispatcher(), {

Maybe we don't want to call the constructor of EventEmitter? It doesn't seem to do much either way.

It would be nice to simplify the setup.

Why not promises?

I'm really curious why you decided to not use any flavour of promises in this implementation (as opposed to the initial version of the dispatcher in TodoMVC).

I can see how the code achieves more or less the same result. And I can understand removing a dependency which can be replaced with just a few lines of smart code. But I'm still curios if there's something more behind this decision.

P.S. this is a bit cheesy, but the team @ anyguide.com wants to thank you guys for all the work you've been doing and we're looking forward to pushing React+Flux in production in ~1month :)

`RECEIVE_RAW_CREATED_MESSAGE` event is never handled

Just wondering what happens when RECEIVE_RAW_CREATED_MESSAGE was dispatched, currently in the code base it was not handled anywhere.

Also, what if ChatWebAPIUtils.createMessage() received error from the XHR call to server, what happens next? Should the data already in Stores and Views be rolled back?

npm install failed

I did fork the code and trying to run the npm install in my MAC. I got the following error? Any help?

[email protected] install /Users/manmada/Desktop/node/todo/flux/examples/flux-todomvc/node_modules/watchify/node_modules/chokidar/node_modules/fsevents
node-gyp rebuild

CXX(target) Release/obj.target/fse/fsevents.o
In file included from ../fsevents.cc:6:

[email protected] install /Users/manmada/Desktop/node/todo/flux/examples/flux-todomvc/node_modules/watchify/node_modules/chokidar/node_modules/fsevents
node-gyp rebuild

CXX(target) Release/obj.target/fse/fsevents.o
In file included from ../fsevents.cc:6:
In file included from ../node_modules/nan/nan.h:133:
/Users/manmada/.node-gyp/0.10.28/deps/uv/include/uv.h:59:10: fatal error: 'sys/types.h' file not found

include <sys/types.h> /* size_t */

     ^

1 error generated.
make: *** [Release/obj.target/fse/fsevents.o] Error 1

304 https://registry.npmjs.org/bindings

304 https://registry.npmjs.org/bindings

[email protected] install /Users/manmada/Desktop/node/todo/flux/examples/flux-todomvc/node_modules/jest-cli/node_modules/jsdom/node_modules/contextify
node-gyp rebuild

CXX(target) Release/obj.target/contextify/src/contextify.o
In file included from ../src/contextify.cc:1:
In file included from /Users/manmada/.node-gyp/0.10.28/src/node.h:61:
/Users/manmada/.node-gyp/0.10.28/deps/uv/include/uv.h:59:10: fatal error: 'sys/types.h' file not found

include <sys/types.h> /* size_t */

     ^

1 error generated.
make: *** [Release/obj.target/contextify/src/contextify.o] Error 1

[email protected] install: node-gyp rebuild
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is most likely a problem with the contextify package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node-gyp rebuild
npm ERR! You can get their info via:
npm ERR! npm owner ls contextify
npm ERR! There is likely additional logging output above.

Why not using the action to do update the stores? (higher compling)

Hy!

Currently I have an app that has a changed version of flux in which the action manages all the stores changes:

  • Some stores;
  • Communicates with the server;
  • Tracking;

I don't need to wait for stores (anyway flux's waitFor() is synchronous), I just put the things in the order. For now is scaling well, but I might wonder what would be the benefits of implementing a strict flux architecture (where the stuff is done in the register callback in each model)?

The first thing that can go wrong is having a lot of stuff in each action. But you have the benefit of knowing in one glance what is going on each action. In the strict flux architecture you would have to open each store and check it's relative action listener.

This is the real action, without any modification:

define(function(require, exports, module){

    var _         = require('underscore');
    var utils     = require('client/utils');
    var async     = require('async');
    var constants = require('client/constants');
    var tempShipIdCounter = 0;
    return function(args, cb){
        var logic = require('client/logic/logic');
        var _this = this;
        var data  = _this.ctx.data;

        var planet  = args.planet;
        var taskId  = args.taskId;
        var payload = args.payload;

        async.series({
            _: function(cb){
                var res = planet.getTask().startTask(taskId, payload, data.authStore.currentPlayer);
                if(res.err){
                    data.popupStore.addPopup('task', {
                        planet    : planet,
                        taskState : 'error',
                        err       : res.err
                    });
                    return;
                }
                _this.api('startTask', res.data, {handleError: true}).then(function(res){
                    if(res.err){
                        if(DEBUG){
                            debugger
                            return console.error(res.err);
                        }else{
                            return location.reload();
                        }
                    }
                })
                // We need to get from the res.data because the taskId can be undefined
                // when we auto-restart last task.
                taskId = res.data.taskTypeId;
                data.sounds.startTask.play(taskId);
                woopra.track('start ' + taskId)
                data.taskStore.trackPlanet(planet);
                data.popupStore.addPopup('task', {
                    added     : res.details.added,
                    task      : planet.getTask().toJSON(),
                    taskState : 'started',
                    planet    : planet
                });

                cb();
            }
        }, cb)
    };
});

Managing amount of client-side data

How should the Stores manage the amount and persistence of data held in the browser?

When views request data from a Store, often it will need to do a server request and then the result I presume would sit in memory as application state. This is great for small amounts of data but what about when that data grows over the lifespan of an application?

At some point a clean-up of unnecessary data in memory needs to happen, but how would you go about doing this?

Hope this makes sense 😉

Rebuild github pages

In your github pages documentation the docs specify the use of: var merge = require('react/lib/merge'); .

Where-as in master/docs/* its been switched to var assign = require('object-assign');.

What about complex alerts (like a popup)?

I'm still trying to figure out how to setup alerts like a popups.

  • Should I have an alert store?
  • Or should the domain store keep some variable to let me know that needs to open the store?

I've tried both approaches and nothing seems correct.

An alert store?

If the contents of the alert has more logic, is managed by whom? The alert can't manage that.
Here is how is done:

  • alertStore.add({contents: new UnlockJob({...})})
  • In my root alertStore.getAll().map(function(alert){return alert})

Or should the domain store keep some variable to let me know that needs to open the store?

How do I open the alert in the first place? I do: myStore.unlockingJob ? new UnlockJob({...}) : null (the UnlockJob is the alert view) in my root component. But then I can't manage any alerts properly.

Potential performance issue in stores in the Chat demo

I'm looking solutions for our single page app built with React and Backbone. And in Backbone, a view listens to its own Model or Collection. So given a View of message, it does not refresh when a message of another room updates.

While in React it appears maintaining Stores like Models is quite a bad idea. In the Chat demo, there is only one MessageStore here.
https://github.com/facebook/flux/tree/master/examples/flux-chat/js/stores
Suppose someone is chatting in room A, updates of room B may trigger a View refresh. When there are hundreds of messages, we may face a issue of performance.

So I quite like to know what's your concern when you wrote the Chat demo, how about that it performance when it gets large?

Example tests

It would be great if the examples included a few (Jest) test cases. Preferably test cases that deal with both components and stores.

Better error handling for dispatcher.register

This is more of best practice suggestion then a bug but caused me some headaches today.

The stores run a switch statement on action.type and match it to your list of constants.

this is where spelling mistakes / random fuck ups can add up in a rather ugly manner.

if for example you forgot to add a specific constant to your list you will basically be comparing undefined to undefined - which will work just fine.

You will catch it the next time you make a similar mistake and multiple actions get fired.

Highly suggest verifying action.type exist before the switch statement :)

Can add a pull req for the examples if this makes sense

Dont use require('react/lib/*') in examples & docs

These are internal and implementation details of how React builds for npm. We're going to deprecate them. merge is now simply Object.assign and copyProperties is a simple for in (and can be replaced with Object.assign)

Should I put logic into ActionCreators?

I have a scenario where an action is to be dispatched however I need to perform some logic dependent on the state of certain stores to determine what actions to dispatch. Since a store cannot dispatch while already dispatching I cannot create a store which handles this logic. Note that this logic is non trivial.

Basically I need to perform an action which says "Calculate and apply a route which brings this resource to that target". The route that the resource has to take depends on available resources provided by the different stores. So I need to query all the stores and perform some logic to figure out what route is the best one and then dispatch the corresponding actions to the stores to make it happen.

Should I put the logic in the ActionCreator? Although that does not quite follow the guidelines which explicitly state the ActionCreators should just be helper methods to create and dispatch the actions.

Issue running flux-todomvc example

Hi,

I was trying to run the flux-todomvc example and followed the instructions but it didn't work. I found that reactify requires / * * @jsx React.DOM */ to be the first line in any .jsx/.js files. Once I added the directive to the top of all the components I was able to get it to work.

Is this just me?

Frank

"npm install flux" fails.

Tried: npm install flux

and got:

npm WARN package.json [email protected] No description
npm WARN package.json [email protected] No repository field.
npm WARN package.json [email protected] No README data
npm WARN install Refusing to install flux as a dependency of itself

Manually added "flux": "^2.0.1" to package.json and then did npm install and it worked.

Can someone explain if the problem is the repo or my node installation (homebrew). Thanks!

Plans to publish to NPM?

E.g. is the code here something you intend for others to use or is just for learning purposes?

Flux To Do Tutorial

This is related to #31. The code in the Flux Todo MVC has a different dispatcher than the tutorial on the site.

This is pretty confusing because I had the tutorial open side by side with the code.

I would be happy to send a PR to update the site but I'm not sure if adding the new dispatcher is the right decision since the previous dispatcher seems shorter and simpler.

Stores and form validation?

There are times when I have form components changing data in a particular domain, and the business logic that governs validation and error states is sufficiently complex. Where is the best place to put that logic?

It seems reasonable to place the logic in Stores so that validation is centralized and easy to test. And those stores can fire error actions an ErrorStore can collect, log, and act upon. But it's unclear to me how you'd surface those errors back to the components that created them.

Another approach is to perform the validation in form components themselves, which seems reasonable for basic validation, but for complex business logic that feels like the wrong place for it.

Any guidance for handling this case?

[Question] Form Wizard

I would like to discuss best practice about form wizard.
Following example. We have a page with 3 components: header, content, footer. In the header we show the name of the step. Content component shows the form for actual step. The footer contains buttons to go to the previous step or to the next step.

Problem 1:

Because the submit button and the form are capsulated in different components, how can we retrieve the data from the form component and submit this data to the server? By clicking on the button in the footer component it fires an action. This action can't contain the form data, because it can't access other components data. The action is received by a store. But the store don't have the form data to send it to server.

Solution 1.

On every input chage in the form, we fire an action with this change and transfer changed input value to the store. So we can guarantee, that the store always has fresh data of the form.
When the store receives the submit action, it sends its data to server.
Disadvantage is that we have to fire on each keypress an action.

Solution 2.

In addition to change event we create in the store a request event. Our form listen to the request event. After receiving a submit action the store emit a request event. The form receives the request event, collects all field data and fire an action with collected data to the store.

Problem 2:

For each step and each form we have different stores. The main process state is handeled by separeted MainStore. MainStore may show a popup with error message.
For example we have 2 forms on one page. Each form have to be validated by server. After we click on submit button each form store receives the submit action and makes an ajax request to validate its form data. If something with data is wrong the MainStore have to show the error messages in the popup. How to synchronize responses from these two async server validations and show the merged response in the popup by the MainStore?

Solution 1.

Centralize all validation actions from all forms in the MainStore. The MainStore executes the ajax requests through a promise lib and after complete of all requests it fires a change event with merged server response. In this solution the MainStore should have write access to other stores to transfert the server field errors to form stores.
Disadvantage is that we have a very big MainStore with whole logic.

Solution 2.

Submit action goes to each form store and each form store makes an ajax request to validate its data. After the form store have received the response from server it has to send the errors to the MainStore, so the MainStore can show the popup with errors.
Disadvantage is that we have to synchronize all ajax responses from to know when to switch to next step in the wizard.
Other disadvantage is that we cant make a logic in sequences of validations. For example execute form A and if (and only if) the validation is OK execute the validation of form B.

the dispatcher wait doesn't actually wait for other callback?

I think flux is a great architecture for building web appliactions, i'm very interested in it

I read the dispatcher soucre code but i can't understand the waitFor method, it's not asynchronous but synchronous.

It makes me confused,is there any store's callback could include some ajax call to server and make a asynchronous example of the waitFor method?

Improve "Cannot dispatch in the middle of a dispatch" error with information on actions

This error is useful to spot cascading actions, but it can sometimes be difficult to track down the cause.

Adding information on the _pendingPayload as well as the payload that triggered the error could be useful. (@iirvine 's Dispatcher has a nice warning message in this spirit: https://github.com/iirvine/fluent-flux/blob/master/src/Dispatcher.js).

How to display each payload? One idea could be having a _displayAction method that you could override when constructing the Dispatcher? Something like:

constructor(options) {
  if (options && options.displayAction) {
    this._displayAction = options.displayAction;
  }  
}

_displayAction(payload) {
  return payload.type;
}

dispatch(payload) {
    invariant(
      !this._isDispatching,
      'Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ' +
      `Received action '${this._displayAction(payload)}' while still dispatching action '${this._displayAction(this._pendingPayload)}'. `
    );
}

I can try to put together a PR for this, but wanted to jot down some ideas here first see what you think...

Where to handle Animations?

Its quite common that a subcomponent like a modal does not just instantaneously appears but that an animation is associated with it. Since the initial user action would be called in an action and communicated to the store, i suppose the store would handle the animation and communicate the state change to the react component ?

Test variables missing var keyword

In TodoStore-test.js the variables at lines 37-39 are missing var, and i think they are going global

beforeEach(function() {
  AppDispatcher = require('../../dispatcher/AppDispatcher');
  TodoStore = require('../TodoStore');
  callback = AppDispatcher.register.mock.calls[0][0];
});

Not a big deal though :)

Make dependency removal?

Is there any reason this project uses make? Could it be replaced with something that npm could install?

What about indirect actions?

  • I have store S1 which listens to actions A1, A2 and A3.
  • Then I have store S2 which only change when the S1 store changes.
  • With flux architecture I have to make S2 also listen on actions A1, A2 and A3?

This is not DRY and can lead to many bugs.

What is your opinion? How to solve this?

Update dispatcher.js in flux-chat

Seems there is a newer version in /src/dispatcher.js, but an older one was used in flux-chat example.

Probably this file should be symlinked from /src to the example dir?

Bring back promises?

The "original" version from the Flux-TodoMVC example used promises for the Dispatcher. Is there a reason why you removed this?

ViewController state effectively a mirror of store contents

This is not really an issue, more of a question, but I couldn't find a place to put it.

As far as I can see, top level ViewControllers end up pretty much just mirroring stores in their state. Is there any reason to do this as opposed to just pulling data straight from the stores and calling forceUpdate on change? My app has 20 ViewControllers and growing, so it adds up to a ton of boilerplate nearly repeated between every ViewController.

Here is all the boilerplate in the TodoApp example, which effectively serves to mirror the TodoStore state into TodoApp's state:

function getTodoState() {
  return {
    allTodos: TodoStore.getAll(),
    areAllComplete: TodoStore.areAllComplete()
  };
}
var TodoApp = React.createClass({
  getInitialState: function() {
    return getTodoState();
  },
  componentDidMount: function() {
    TodoStore.addChangeListener(this._onChange);
  },
  componentWillUnmount: function() {
    TodoStore.removeChangeListener(this._onChange);
  },
  _onChange: function() {
    this.setState(getTodoState());
  }
});

module.exports = TodoApp;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.