Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Understanding Async Requests #112

Closed
jrogozen opened this issue Mar 3, 2015 · 6 comments
Closed

Understanding Async Requests #112

jrogozen opened this issue Mar 3, 2015 · 6 comments

Comments

@jrogozen
Copy link

jrogozen commented Mar 3, 2015

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.

@jrogozen
Copy link
Author

jrogozen commented Mar 3, 2015

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?)

@BinaryMuse
Copy link
Owner

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.

@BinaryMuse
Copy link
Owner

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);
  }
}

@jrogozen
Copy link
Author

jrogozen commented Mar 3, 2015

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

@BinaryMuse
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants