BinaryMuse / fluxxor

:hammer_and_wrench: Flux architecture tools for React

Home Page:http://fluxxor.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Understanding Async Requests

jrogozen opened this issue · comments

commented

Hi,

I'm trying to wrap my head around async requests with Fluxxor.

Is this the correct flow?

  • Component triggers action
  • Store takes action and calls function
  • Function has async operation that results in changed data within store / emit('change') call
  • View re-renders with the new data

If this is how it works, does the view render BEFORE data is retrieved from an api/server call once, and then again afterwards?

For example, I'm trying to write a comment component that uses Disqus to display comment threads for posts within a blog app. Without using Fluxxor, I'd pass the post data as props to a Comment component, which would load the Disqus js file/options. But, doing it this way I'd have to deal with somehow making sure I'm not doing anything with the new props before they've been resolved as passed in.

Does Fluxxor have a good way of dealing with this async passing of data between components? Would I want my Post component to trigger an action that results in data in the store, which the Comment component then pulls from? How can I ensure that the Comment component is only loading data from the store once it's been resolved?

  • Post component triggers action
  • Store takes action and makes API call
  • Store stores data from result and triggers change event
  • View re-renders
  • Child component is triggered to render (??)

In my specific case, if the child component renders before the data has finished resolving, the comments won't load correctly, even if it's rendered again with new data a second later.

commented

Thanks for the resources!

So the flow of data would be

  • Post component triggers action
  • action makes async request and dispatches accordingly to the store
  • store binds events to functions, which set data in the store based on results

I still don't quite understand how I can tell a child component to not try to grab data from a store until it has it defined.

For example:

  • Post component triggers action
  • action makes async request and is waiting to dispatch a success/failure to the store
  • Child component renders, componentDidMount triggers with a call to get data from the store (returns undefined)
  • Original action completes, store handler function is called and change event is emitted

In this case, the child component will have already attempted an action with no data before it is told something has changed (or am I not understanding how this works properly?)

When the child requests the data from the store, the store doesn't have to return undefined. It could just as easily return some token indicating that the data is still loading; the child component would conditionally render (or render something different, like a loading indicator) based on that value.

To elaborate, consider the following example, which assumes comments are loaded with the post (if they aren't, you could easily extract into multiple API calls/multiple actions/multiple stores as necessary):

Action Creators:

loadPost(postId) {
  this.dispatch("LOAD_POST_START", {postId});

  myApi.fetchPost(postId).then((postData) => {
    this.dispatch("LOAD_POST_SUCCESS", {postId: postId, post: postData});
  }, (error) => {
    this.dispatch("LOAD_POST_ERROR", {postId: postId, error: err});
  });
}

Post Store:

initialize() {
  this.bindActions(
    "LOAD_POST_START", this.handleLoadPostStart,
    "LOAD_POST_SUCCESS", this.handleLoadPostSuccess
  )
},

handleLoadPostStart({postId}) {
  this.posts[postId] = LOADING_TOKEN;
  this.emit("change");
},

handleLoadPostSuccess({postId, post}) {
  this.posts[postId] = post;
  this.emit("change");
}

Comment Component:

getStateFromFlux() {
  var postsStore = this.getFlux().store("posts")
  return { comments: postsStore.getPost(this.props.postId).comments };
},

render() {
  if (this.state.comments === LOADING_TOKEN) {
    return <LoadingSpinner />;
  } else {
    return this.renderComments(this.state.comments);
  }
}
commented

Thanks so much, this is exactly what I was looking for

Going to close this issue, please feel free to comment or re-open if you have more trouble/questions!