Let me explain the problem that I have recently encountered.
I have a React.js + Flux application:
- There is a list of article lists (NOTE: there are several different lists in the appendix) and a details view article inside it.
- But for each list, there is only one API endpoint that returns an array of articles.
- To display the details, I need to
find article by id in the array. It works very well. I run an action that makes a request to the server and distributes the data store, when I go to the details screen, then I just get the desired article from this array in the store. - When the user starts to present the details of the article in front of the list (stores are empty), then I need to make a request.
- The flow looks like this:
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 A component may look like this:
let DetailsComponent = React.createClass({ _getStateFromStores() { let { articleId } = this.getParams(); return { article: ArticleStore.getArticle(articleId) }; }, componentDidMount() {
The interesting part is as follows:
- Now I need to make another request to the server, but the request parameters depend on the details of the article . This is why I need to make a second request after the first in the details view.
- I tried several approaches, but they all look ugly. I donβt like triggering actions from stores, which makes stores too complex. Invoking actions inside an action in this case does not work, because I need to find an article from the repository inside this action.
Decision (?!)
What I came up with is to use the callback in action inside the component, and it feels a lot 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 is your input?
source share