bootstrap javascript reactjs architecture redux flux

javascript - bootstrap - Redux: organizando contenedores, componentes, acciones y reductores



popover js (1)

La pregunta:

¿Cuál es la mejor práctica recomendada y más fácil de mantener para organizar contenedores, componentes, acciones y reductores en una aplicación grande de React / Redux ?

Mi opinión:

Las tendencias actuales parecen organizar garantías reductoras (acciones, reductores, sagas ...) alrededor del componente contenedor asociado. p.ej

/src /components /... /contianers /BookList actions.js constants.js reducer.js selectors.js sagas.js index.js /BookSingle actions.js constants.js reducer.js selectors.js sagas.js index.js app.js routes.js

Esto funciona genial! Aunque parece haber un par de problemas con este diseño.

Los problemas:

Cuando necesitamos acceder a actions , selectors o sagas desde otro contenedor parece un antipatrón. Digamos que tenemos un contenedor global /App con un reductor / estado que almacena la información que utilizamos en toda la aplicación, como categorías y enumerables. Siguiendo con el ejemplo anterior, con un árbol de estado:

{ app: { taxonomies: { genres: [genre, genre, genre], year: [year, year, year], subject: [subject,subject,subject], } } books: { entities: { books: [book, book, book, book], chapters: [chapter, chapter, chapter], authors: [author,author,author], } }, book: { entities: { book: book, chapters: [chapter, chapter, chapter], author: author, } }, }

Si queremos usar un selector del contenedor /App dentro de nuestro contenedor /BookList necesitamos recrearlo en /BookList/selectors.js (¿seguramente está mal?) O importarlo desde /App/selectors (¿será siempre el EXACTO? mismo selector ...? no). Ambos estos appraoches me parecen poco óptimos.

El mejor ejemplo de este caso de uso es Autenticación (ah ... auth nos encanta odiarte) ya que es un modelo MUY común de "efecto secundario". A menudo necesitamos acceder /Auth sagas, acciones y selectores por toda la aplicación. Es posible que tengamos los contenedores /PasswordRecover , /PasswordReset , /Login , /Signup ... ¡De hecho, en nuestra aplicación nuestro /Auth contianer no tiene ningún componente real!

/src /contianers /Auth actions.js constants.js reducer.js selectors.js sagas.js

Simplemente contiene todas las garantías de Redux para los diversos contenedores de autenticación a menudo no relacionados mencionados anteriormente.


Yo personalmente uso la propuesta packs-modular-redux .

No es la manera recomendada "oficial", pero funciona muy bien para mí. Cada "pato" contiene los actionTypes.js , actionCreators.js , sagas.js , sagas.js y selectors.js . No hay dependencia de otros patos en estos archivos para evitar la dependencia cíclica o el círculo de pato , cada "pato" contiene solo la lógica que debe administrarse.

Luego, en la raíz, tengo un components y una carpeta de containers y algunos archivos raíz:

components/ carpeta contiene todos los componentes puros de mi aplicación

containers/ carpeta contiene contenedores creados a partir de componentes puros arriba. Cuando un contenedor necesita un selector específico que involucre muchos "patos", lo escribo en el mismo archivo donde escribí el componente <Container/> , ya que es relativo a este contenedor específico. Si el selector se comparte por varios contenedores, lo creo en un archivo separado (o en un HoC que proporciona estos accesorios).

rootReducers.js : simplemente expone los reductores de raíz combinando todos los reductores

rootSelectors.js expone el selector de raíz para cada porción de estado; por ejemplo, en su caso podría tener algo como:

/* let''s consider this state shape state = { books: { items: { // id ordered book items ... } }, taxonomies: { items: { // id ordered taxonomy items ... } } } */ export const getBooksRoot = (state) => state.books export const getTaxonomiesRoot = (state) => state.taxonomies

Nos permite "ocultar" la forma del estado dentro de cada archivo selectors.js patos. Como cada selector recibe el estado completo dentro de sus patos, simplemente tiene que importar el rootSelector correspondiente dentro de sus archivos selector.js .

rootSagas.js compone todas las sagas dentro de tus patos y administra un flujo complejo que involucra a muchos "patos".

Entonces en tu caso, la estructura podría ser:

components/ containers/ ducks/ Books/ actionTypes.js actionCreators.js reducers.js selectors.js sagas.js Taxonomies/ actionTypes.js actionCreators.js reducers.js selectors.js sagas.js rootSelectors.js rootReducers.js rootSagas.js

Cuando mis "patos" son lo suficientemente pequeños, a menudo me salteo la creación de la carpeta y escribo directamente un ducks/Books.js o ducks/Taxonomies.js con todos estos 5 archivos ( actionTypes.js , actionCreators.js , actionCreators.js , selectors.js , sagas.js ) fusionados.