Sto creando una semplice app CRUD utilizzando Flux Dispatcher di Facebook per gestire la creazione e la modifica di post per un sito di apprendimento in inglese. Attualmente occupo di un'API che assomiglia a questo:Come gestire le chiamate api annidate in flusso
/posts/:post_id
/posts/:post_id/sentences
/sentences/:sentence_id/words
/sentences/:sentence_id/grammars
nello show e modificare pagine per l'applicazione, mi piacerebbe essere in grado di mostrare tutte le informazioni per un determinato posto, così come tutti le frasi e le parole delle parole e i dettagli della grammatica si trovano tutti su un'unica pagina.
Il problema che sto colpendo è capire come avviare tutte le chiamate asincrone richieste per raccogliere tutti questi dati e quindi comporre i dati che ho bisogno da tutti i negozi in un singolo oggetto che posso impostare come stato in il mio componente di livello superiore. Una corrente (terribile) esempio di quello che ho cercato di fare è questo:
Il livello superiore PostsShowView:
class PostsShow extends React.Component {
componentWillMount() {
// this id is populated by react-router when the app hits the /posts/:id route
PostsActions.get({id: this.props.params.id});
PostsStore.addChangeListener(this._handlePostsStoreChange);
SentencesStore.addChangeListener(this._handleSentencesStoreChange);
GrammarsStore.addChangeListener(this._handleGrammarsStoreChange);
WordsStore.addChangeListener(this._handleWordsStoreChange);
}
componentWillUnmount() {
PostsStore.removeChangeListener(this._handlePostsStoreChange);
SentencesStore.removeChangeListener(this._handleSentencesStoreChange);
GrammarsStore.removeChangeListener(this._handleGrammarsStoreChange);
WordsStore.removeChangeListener(this._handleWordsStoreChange);
}
_handlePostsStoreChange() {
let posts = PostsStore.getState().posts;
let post = posts[this.props.params.id];
this.setState({post: post});
SentencesActions.fetch({postId: post.id});
}
_handleSentencesStoreChange() {
let sentences = SentencesStore.getState().sentences;
this.setState(function(state, sentences) {
state.post.sentences = sentences;
});
sentences.forEach((sentence) => {
GrammarsActions.fetch({sentenceId: sentence.id})
WordsActions.fetch({sentenceId: sentence.id})
})
}
_handleGrammarsStoreChange() {
let grammars = GrammarsStore.getState().grammars;
this.setState(function(state, grammars) {
state.post.grammars = grammars;
});
}
_handleWordsStoreChange() {
let words = WordsStore.getState().words;
this.setState(function(state, words) {
state.post.words = words;
});
}
}
Ed ecco la mia PostsActions.js - le altre entità (sentenze, grammatiche, parole) hanno anche ActionCreators simili che funzionano in modo simile:
let api = require('api');
class PostsActions {
get(params = {}) {
this._dispatcher.dispatch({
actionType: AdminAppConstants.FETCHING_POST
});
api.posts.fetch(params, (err, res) => {
let payload, post;
if (err) {
payload = {
actionType: AdminAppConstants.FETCH_POST_FAILURE
}
}
else {
post = res.body;
payload = {
actionType: AdminAppConstants.FETCH_POST_SUCCESS,
post: post
}
}
this._dispatcher.dispatch(payload)
});
}
}
il problema principale è che il dispatcher Flux getta "Impossibile inviare nel bel mezzo di un dispaccio" errore invariata quando SentencesActions.fetch
viene chiamato nel _handlePostsStoreChange
callback becau Se il metodo SentencesActions attiva una distribuzione prima che la richiamata di dispatch per l'azione precedente sia terminata.
Sono consapevole che posso risolvere il problema utilizzando qualcosa come _.defer
o setTimeout
- tuttavia sembra davvero che io stia semplicemente correggendo il problema qui. Inoltre, ho considerato di fare tutta questa logica di recupero nelle azioni stesse, ma anche questo non sembrava corretto e renderebbe più difficile la gestione degli errori. Ho ciascuna delle mie entità separata nei propri negozi e azioni - non dovrebbe esserci qualche modo nel livello dei componenti per comporre quello che mi serve dai rispettivi negozi di ogni entità?
Aperto a qualsiasi consiglio da chiunque abbia realizzato qualcosa di simile!
hai provato a utilizzare 'waitFor'? https://facebook.github.io/flux/docs/dispatcher.html – knowbody
@knowbody Sì, ho provato a utilizzare 'waitFor', ma non sembra che risolva il problema, poiché il problema è che un la seconda azione viene inviata prima che il primo possa terminare. Tuttavia, forse la mia comprensione di 'waitFor' è sbagliata e non sto semplicemente usando correttamente? – joeellis
@joeellis: è possibile mettere insieme una demo di jsFiddle per dimostrare la situazione del problema? –