reconoce que interno instalar ingles externo español con como comandos comando javascript node.js reactjs flux

javascript - que - Flux/Alt dependencia de datos, cómo manejar elegantemente y idiomáticamente



yarn npm (3)

Esto definitivamente parece un defecto en el diseño Flux, y tienes razón, es un caso de uso muy común. He estado investigando este tema (y algunos similares) durante unos días para implementar Flux mejor en mi propio sistema, y ​​si bien definitivamente hay opciones, la mayoría tienen inconvenientes.

La solución más popular parece estar usando Contenedores, como AltContainer , para abstraer la tarea de los datos que se solicitan desde apis y cargar desde las tiendas en un solo componente, ausente de ui-logic. Este contenedor sería responsable de ver la información de las tiendas y determinar si se requieren acciones adicionales para completarlas. Por ejemplo;

static getPropsFromStores() { var data = SomeStore.getState(); if (/*test if data is incomplete */){ SomeAction.fetchAdditionalData(); } return data; }

Que tiene sentido. Tenemos la lógica y el componente en nuestra capa de Componente, que es donde Flux dice que pertenece.

Hasta que considere la posibilidad de tener dos contenedores montados pidiendo la misma información (y duplicando así las recuperaciones de inicialización, es decir, conversaciones en su modelo), y el problema solo empeorará si agrega un tercer (o cuarto, o quinto) contenedor que acceda esas mismas tiendas.

La respuesta enlatada a eso de la multitud de Container es "¡Simplemente no tengo más de uno!", Lo cual es un gran consejo ... si sus requisitos están bien con eso.

Así que aquí está mi solución alterada, alrededor del mismo concepto; Incluya un contenedor maestro / componente en toda su aplicación (o incluso al lado). A diferencia de los contenedores tradicionales, este contenedor maestro / componente no pasará propiedades de la tienda a sus hijos. En cambio, es el único responsable de la integridad y finalización de los datos.

Aquí hay una implementación de muestra;

class JobStore { constructor() { this.bindListeners({ handleJobUpdate: jobActions.success }); }, handleJobUpdate(jobs) { this.jobs = jobs; } } class ConversationStore { constructor() { this.bindListeners({ handleJobUpdate: jobActions.success, handleConversationUpdate: conversationActions.success }); }, handleJobUpdate(jobs) { this.conversations = {}; this.tmpFetchInfo = jobs.conversation_id; this.isReady = false; }, handleConversationUpdate(conversations) { this.conversations = conversations; this.tmpFetchInfo = ''''; this.isReady = true; } } class MasterDataContainer { static getPropsFromStores() { var jobData = JobStore.getState(); var conversationData = ConversationStore.getState(); if (!conversationData.isReady){ ConversationAction.fetchConversations(conversationData.tmpFetchInfo); } }, render: function(){ return <div></div>; } }

Estoy usando alt como implementación de flujo para un proyecto y tengo problemas para entender la mejor manera de manejar las tiendas de carga para dos entidades relacionadas. Estoy usando la función de fuentes junto con registerAsync para manejar mis llamadas async / api y vincularlas a mis vistas usando AltContainer.

Tengo dos entidades relacionadas uno a uno por la conversationId. Ambos se cargan a través de una llamada de API:

Una vez que mi tienda de trabajo esté cargada con datos, quiero llenar una tienda de conversación.

Yo uso una fuente para cargar la tienda de trabajo:

module.exports = { fetchJobs() { return { remote() { return axios.get(''api/platform/jobs''); },....

Parece un trabajo para el método waitFor () , pero parece usarse cuando los contenidos de una tienda requieren una transformación o fusión con los contenidos de otra. Necesito buscar los contenidos de un almacén de datos en función del contenido de otro.

En términos generales, necesito:

  • Llamar a una API de terceros y cargar una lista de entidades en una tienda.
  • Cuando lleguen esos datos, necesito usar el atributo de cada uno de los anteriores para llamar a otra API y cargar esos datos en otra tienda.

Mi ingenua solución es hacer referencia a las acciones de conversación desde la tienda de trabajo y enviar un evento cuando lleguen los datos. Algo como esto:

var jobActions = require(''../actions/Jobs''); var conversationActions = require(''../actions/Conversations''); class JobStore { constructor() { this.bindListeners({ handlefullUpdate: actions.success });... } handlefullUpdate(jobs) { this.jobs = jobs; conversationActions.fetch.defer(jobs); } }

Por supuesto, al hacer esto, se viola el dictum de que las tiendas no deben despachar eventos, por lo que debo usar el aplazamiento para enviar una acción en el medio de un despacho. Tiene sentido para mí, ya que parece que al seguir este camino estoy reintroduciendo todo tipo de efectos secundarios en mi código; perdiendo la belleza de los "conductos funcionales" que debería ver con flujo.

Además, mi tienda de trabajo tiene que mantener una referencia a las entidades dependientes para que pueda enviar la acción adecuada. Aquí tengo solo uno, pero podría imaginar muchos. En términos de las dependencias entre las entidades, esto parece totalmente al revés.

Me vienen a la mente un par de alternativas:

Puedo llamar al punto final de la API / plataforma / trabajos en la fuente / acción donde busco todas las conversaciones, solo para obtener la identificación. El enfoque original es más eficiente, pero esto parece más cierto para el espíritu de flujo en el que pierdo toda la conversación cruzada.

También podría tener una sola acción / fuente que recupere ambos, devuelva {jobs:{}, conversations: in the action} (orquestar la dependencia allí usando promesas) y use esto para llenar ambas tiendas. Pero este enfoque me parece innecesariamente complicado (¡siento que no debería tener que hacerlo!).

¿Pero me estoy perdiendo otra manera? Parece extraño que un caso de uso tan común rompa la elegancia del paradim de flujo y / o me obligue a saltar tantos aros.

@dougajmcdonald planteó una pregunta similar aquí , pero tal vez fue formulada en términos generales, y no obtuvo ninguna tracción:


He estado mirando la respuesta de @gravityplanx, pero no estoy seguro de cuánto mejora la situación.

Para reiterar y amplificar: realmente me gusta mucho el patrón alternativo de cargar mis tiendas desde una fuente. Cada componente que necesita una (s) tienda (s) se ve más o menos así:

export default class extends React.Component { componentDidMount() { CurrentUser.fetch(); Jobs.fetch(); }; render() { return( <AltContainer stores={{user:CurrentUser, jobs:Jobs}}> <Body/> </AltContainer>) } }

La intención es comprensible de un vistazo. Y obtengo una clara separación de preocupaciones, lo que hace más fácil probar mis acciones / tiendas y fuentes.

Pero el bello patrón se rompe en el caso de uso común de mi pregunta, y termino creando una tubería bastante complicada en mis acciones y tiendas para orquestar las llamadas ajax para las conversaciones. La otra respuesta parece desplazar esta complejidad a otra parte. Quiero que se vaya.

Lo que terminé haciendo fue separar por completo las tiendas (la primera solución sugerida en la pregunta). Hago una llamada extra a AJAX para recuperar la conversación de un trabajo y otra para buscar las conversaciones en la fuente de JobConversation. Algo como esto:

axios.get(window.taxFyleApi + ''api/platform/active-jobs-pick/layerConversation?jobId='' + jobId) .then((res)=> { let job = res.data[0]; //Returns an array with only one item let qBuilder = window.layer.QueryBuilder.messages().forConversation(job.conversationId)...

Preservar la buena manera de usar AltContainer con mis componentes y perder toda la fontanería de orquestación. En este momento, creo que la claridad resultante vale la pena la llamada extra back-end.

También me doy cuenta de cómo me gustaría que funcione (en términos de notación), y le preguntaré a @goatslacker, o podría intentarlo yo mismo. Me gustaría poder especificar la dependencia en el método exportAsync () en una tienda. Me encantaría poder decir:

class JobConvesationStore { constructor() { this.exportAsync(source, JobStore); }

El método asíncrono JobConversationStore no se llamaría hasta que la JobStore tuviera sus datos. La intención es fácil de leer y no se necesitaría ninguna coreografía de acción compleja.


La mejor solución con la que he llegado hasta ahora (y la que parecen seguir los ejemplos) es agregar una acción "jobsFetched" a mis acciones de trabajo y enviarla cuando lleguen los datos.

var jobActions = require(''../actions/Jobs''); var ConversationActions = require(''../actions/Conversations''); class JobStore { constructor() { this.bindListeners({ handlefullUpdate: jobActions.success... });... } handlefullUpdate(jobs) { this.jobs = jobs; ConversationActions.jobsFetched.defer(jobs); } } class ConversationStore { constructor() { this.bindListeners({ handleJobUpdate: jobActions.jobsFetched... });... } handleJobUpdate(jobs) { /*Now kick off some other action like "fetchConversations" or do the ajax call right here?*/ } }

Esto elimina el problema de que la tienda de trabajos tenga que mantener una referencia a todos sus objetos dependientes, pero aún tengo que llamar una acción desde el interior de mi tienda, y tengo que presentar la acción jobsFetched que configura la tienda de conversación para recuperar sus datos. Parece que no puedo usar una fuente para mis conversaciones.

¿Alguien puede hacerlo mejor?