Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flux + React.js - Callback in actions is good or bad?

Let me explain the problem that I've faced recently.

I have React.js + Flux powered application:

  • There is a list view of articles (NOTE: there are multiple of of different lists in the app) and article details view inside it.
  • But there is only one API endpoint per each list which returns array of articles.
  • In order to display the details I need to find article by id in array. That works pretty fine. I trigger action which makes request to server and propagates store with data, when I go to details screen then I just get the necessary article from that array in store.
  • When user lands on article details view before list (stores are empty) then I need to make a request.
  • Flow looks like: User loads details view -> component did mount -> stores are empty -> rendered empty -> fetchArticles action is triggered -> request response is 200 -> stores now have list of articles -> component did update -> rendered with data successfully
  • Component could look as follows:

    let DetailsComponent = React.createClass({
       _getStateFromStores() {
           let { articleId } = this.getParams();
           return {
               article: ArticleStore.getArticle(articleId)
           };
       },
    
       componentDidMount() {
           // fire only if user wasn't on the list before
           // stores are empty
           if (!this.state.article) {
              ArticleActions.fetchArticles('listType');
           }
       },
    
       render() {
          return <ArticleDetails article={this.state.article} />;
       }
    });
    

The interesting part comes next:

  • Now I need to make another request to server but request options depend on the article details. That's why I need to make second request after the first one on the details view.
  • I've tried several approaches but all of them look ugly. I don't like calling actions from stores that makes stores too complicated. Calling action inside action in this case doesn't work well because I will need to find article from store inside that action.

Solution (?!)

  • What I've came up with is to use callback in action inside component and it feels much more cleaner:

    let DetailsComponent = React.createClass({
       _getStateFromStores() {
           let { articleId } = this.getParams();
           return {
               article: ArticleStore.getArticle(articleId)
           };
       },
    
       componentDidMount() {
           if (!this.state.article) {
              ArticleActions.fetchArticles('listType', () => {
                  this._requestAdditionalData();
              });
           }
           this._requestAdditionalData();
       },
    
       _requestAdditionalData() {
           if (this.state.article) {
              ArticleActions.fetchAdditional(this.state.article.property);
           }
       },
    
       render() {
          return <ArticleDetails article={this.state.article} />;
       }
    });
    

What's your input?

like image 474
Kosmetika Avatar asked Oct 31 '22 08:10

Kosmetika


1 Answers

Consider move the second call to get a detail article to the ArticleDetails component componentDidMount() life cycle method.

So if the article is not set, do not render the ArticleDetails component at all by return null / false.

like image 134
IcyBright Avatar answered Nov 07 '22 22:11

IcyBright