5

I recently used reflux in my project and here is a question puzzled me a lot.
As the reflux pattern, I call actions in my React components, and fetch remote data in my reflux store which are listening to the actions. And my components listen to the changing of data in store. For example get a list of items. So far it's fine.
But sometimes, I want a notification which can told me that the action has executed successfully.
For example, I have a UserStore, a UserActions and a LoginComponent which listen to UserStore. when users have input username and password and click a submit button, the LoginComponent call UserActions.login(), and I send login request in UserStore. When login succeed, UserStore gets user infos from the response.
In this time, I want to give an prompt in LoginComponent such as 'Login Success'. I have two ways to do it but I don't think either is good enough.

  1. Give a flag in the data of UserStore then trigger changing. LoginComponent gets this flag when UserStore trigger a data change event, and then prompt. Because the UserStore would trigger data change not only in login success but also in some other situations like fetching user infos from cookies or sessionStorage, LoginComponent has to add an if-else for this login success flag, if it is login success then prompt.
    I don't think it is a good pattern because that the flag is just for the prompt and NOT a real data like user's infos. And if I also want prompt after user change password, I will need another flag field.
  2. Pass a promise(or a callback function) to the UserAction call, and resolve this promise after login succeed, then the LoginComponent can prompt in promise.then. It's seem better than the first one, but isn't it a little anti-pattern because the promise which been passed through actions to stores may broke the Unidirectional in reflux?

What I want to ask is: What's the common/appropriate way to solve this problem?

I'm not from an English area and not good at English expression. This is my first question in stackoverflow.com. I'm not very sure if I have described my question clearly. So if you have some advice to me about the question, please let me know and I will improve it to help others who care about this question. Thanks a lot!

Zhang Chao
  • 757
  • 4
  • 14
  • I think that there is no problem with both of your attitudes. it won't break the unidirectional concept of flux because when the view change it fires the action which is listened by store. the store makes it's changes then updates the view, with trigger. I had same dilemmas as you do, though not on async calls. you can read it in my blog post http://www.dimagimburg.com/reflux-sweeper-react-reflux-and-immutablejs-explained-by-example/ – Dima Gimburg Dec 13 '15 at 21:19
  • @DimaGimburg Thanks! Maybe I worried too much about it. – Zhang Chao Dec 14 '15 at 07:14

1 Answers1

1

You can include a parameter in the trigger.

export default class AppCtrl extends AppCtrlRender {
  constructor() {
    super();
    this.state = getState();
  }

  componentDidMount = () => { this.unsubscribe = BasicStore.listen(this.storeDidChange); }
  componentWillUnmount = () => { this.unsubscribe(); }
  storeDidChange = (id) => {
    switch (id) {
      case 'data1': this.setState({Data1: BasicStore.getData1()}); break;
      case 'data2': this.setState({Data2: BasicStore.getData2()}); break;
      case 'data3': this.setState({Data3: BasicStore.getData3()}); break;
      default: this.setState(getState());
    }
  }
}

import Reflux from 'reflux';

import Actions from '../actions/sa.Actions';
import AddonStore from './Addon.Store';
import MixinStoreObject from './Mixin.Store';

function _GotData(data) { this.data1 = data; BasicStore.trigger('data1'); }

let BasicStoreObject = {
  init() { this.listenTo(AddonStore, this.onAddonTrigger); },
  data1: {},
  listenables: Actions,
  mixins: [MixinStoreObject],
  onGotData1: _GotData,
  onAddonTrigger() { BasicStore.trigger('data2'); },
  getData1() { return this.data1; },
  getData2() { return AddonStore.data2; },
  getData3() { return this.data3; }
}
const BasicStore = Reflux.createStore(BasicStoreObject);
export default BasicStore;
J. Mark Stevens
  • 4,911
  • 2
  • 13
  • 18
  • I am a little confused with the `BasicStore.getData1()` things. I was thinking that stores are listened by components and all data should be transfered (only) by `trigger`. So is it a little 'anti-pattern' that fetch data directly from store using functions like `BasicStore.getData1()` ? – Zhang Chao Jan 01 '16 at 04:08
  • In a complex app with many data elements limiting oneself to data returned by the trigger would not be practical. Whereas in a simple app it might work. Reflux provides the flexibility to use the method best suited to your needs. – J. Mark Stevens Jan 01 '16 at 18:27