问题
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?
回答1:
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.
来源:https://stackoverflow.com/questions/29148539/flux-react-js-callback-in-actions-is-good-or-bad