kenwheeler / mcfly

Flux architecture made easy
BSD 3-Clause "New" or "Revised" License
762 stars 46 forks source link

Textarea's cursor jumps when changing its value through McFly #51

Open ferrannp opened 9 years ago

ferrannp commented 9 years ago

So I came into the same exact issue as this one for reflux: https://github.com/reflux/refluxjs/issues/43

Using Flux flow Action → Store → View Like:

render: function() {
  return (
    <textarea
      value={this.props.value}
      onChange={this.handleChange}
    />
  );
},

handleChange: function(ev) {
  Actions.updateMessage(ev.target.value);
}

The problem is that typing anything when the cursor is not at the end of the box, will make the cursor to jump to the end of that box.

In the link I posted above, looks like that framework has a sync flag to make actions sync and the issue does not appear. I suppose here is happening because our actions are promises?

Any idea on how to solve this? Could we add to McFly a similar flag?

@tomatau did you run into similar issues in your projects?

ferrannp commented 9 years ago

@kenwheeler I tested it changing the promise for normal callback (like in versions previous to 0.0.8) and it works fine. Could we add a flag to decide when we want an action to be a promise or when we want to be sync?

rgommezz commented 9 years ago

+1, it happens the same to me

kenwheeler commented 9 years ago

good call, adding a sync flag

ferrannp commented 9 years ago

Hey man, thank you! I was playing with it myself but I'm pretty sure you'll find a better approach. Just for fun I'll leave it here:

So I make that you can define an action as an array too, like:

  myAction: [
    function(someParam){
      return {
        actionType: 'CHANGE_TEXT',
        text: someParam
      }
    },
    true //Sync! to avoid: https://github.com/kenwheeler/mcfly/issues/51
  ],

Then I change ActionFactory.js:

if(actions[a].constructor === Array){
  action = new Action(actions[a][0], actions[a][1]);
}else {
  action = new Action(actions[a]);
}

And well, in the Action.js:

  function Action(callback, sync) {
    this.callback = callback;
    this.sync = sync;
  }

  function dispatchHelper(payload) {
    if (!payload) return reject();
    if (!payload.actionType) return reThrow(reject,
      "Payload object requires an actionType property"
    );
    try {
      Dispatcher.dispatch(payload);
    } catch (error) {
      reThrow(reject, error);
    }
  }

  Action.prototype.dispatch=function() {"use strict";

    if(this.sync !== true) {
      return Promise.resolve(this.callback.apply(this, arguments))
        .then(function(payload){
          return new Promise(function(resolve, reject){
            dispatchHelper(payload);
            resolve();
          });
        });
    }else {
      var payload = this.callback.apply(this, arguments);
      dispatchHelper(payload);
    }
  };

Does this make sense?

ferrannp commented 8 years ago

hey @kenwheeler, any news on this?