Presentación y Componentes de Contenedor

Bismuto

Actualización de 2019: escribí este artículo hace mucho tiempo y mis puntos de vista han evolucionado. En particular, ya no sugiero dividir sus componentes de esta manera. Si lo encuentras natural en tu base de código, este patrón puede ser útil. Pero he visto que se impone sin necesidad alguna y con fervor casi dogmático demasiadas veces. La razón principal por la que lo encontré útil fue porque me permitió separar la lógica compleja con estado de otros aspectos del componente. Los ganchos me permiten hacer lo mismo sin una división arbitraria. Este texto se deja intacto por razones históricas, pero no lo tomes demasiado en serio.

Hay un patrón simple que encuentro inmensamente útil al escribir aplicaciones React. Si has estado haciendo React por un tiempo, probablemente ya lo hayas descubierto. Este artículo lo explica bien, pero quiero añadir algunos puntos más.

Encontrará que sus componentes son mucho más fáciles de reutilizar y razonar si los divide en dos categorías. Los llamo Contenedores y Componentes de Presentación*, pero también escuché Gordos y Delgados, Inteligentes y Tontos,con Estado y Puros, Pantallas y Componentes, etc. Todos estos no son exactamente los mismos, pero la idea central es similar.

Mis componentes de presentación:

  • Están preocupados por cómo se ven las cosas.
  • Puede contener componentes de presentación y contenedor * * en su interior, y por lo general tienen algunos estilos y marcas DOM propios.
  • A menudo permiten la contención a través de esto.apoyos.niño.
  • No tienen dependencias en el resto de la aplicación, como acciones de flujo o tiendas.
  • No especifique cómo se cargan o mutan los datos.
  • Recibe datos y devoluciones de llamada exclusivamente a través de accesorios.
  • Rara vez tienen su propio estado (cuando lo hacen, es el estado de la interfaz de usuario en lugar de los datos).
  • Se escriben como componentes funcionales a menos que necesiten estado, ganchos de ciclo de vida u optimizaciones de rendimiento.
  • Ejemplos: Página, Barra lateral, Historia, Información de usuario, Lista.

Componentes de mi contenedor:

  • Se preocupan por cómo funcionan las cosas.
  • Puede contener componentes de presentación y contenedor** dentro, pero generalmente no tienen ningún marcado DOM propio, excepto algunos divs de envoltura, y nunca tienen estilos.
  • Proporcione los datos y el comportamiento a los componentes presentacionales u otros componentes del contenedor.
  • Llama a acciones de flujo y las proporciona como devoluciones de llamada a los componentes de presentación.
  • Son a menudo con estado, ya que tienden a servir como fuentes de datos.
  • Generalmente se generan utilizando componentes de orden superior como connect() de React Redux, createContainer () de Relé o Contenedor.create () a partir de Flux Utils, en lugar de escribirlo a mano.
  • Ejemplos: UserPage, FollowersSidebar, StoryContainer, FollowedUserList.

Los puse en diferentes carpetas para hacer esta distinción clara.

Beneficios de Este Enfoque

  • Mejor separación de preocupaciones. Comprendes mejor tu aplicación y tu interfaz de usuario al escribir componentes de esta manera.
  • Mejor reutilización. Puede usar el mismo componente de presentación con fuentes de estado completamente diferentes y convertirlas en componentes contenedores separados que se pueden reutilizar aún más.
  • Los componentes de presentación son esencialmente la “paleta”de su aplicación. Puedes ponerlos en una sola página y dejar que el diseñador ajuste todas sus variaciones sin tocar la lógica de la aplicación. Puede ejecutar pruebas de regresión de capturas de pantalla en esa página.
  • Esto le obliga a extraer “componentes de diseño” como Barra lateral, Página, Menú contextual y usar esto.apoyos.hijos en lugar de duplicar el mismo marcado y diseño en varios componentes contenedores.

Recuerde, los componentes no tienen que emitir DOM. Solo necesitan proporcionar límites de composición entre las preocupaciones de la interfaz de usuario.

Aproveche eso.

¿Cuándo introducir Envases?

Le sugiero que comience a crear su aplicación con solo componentes de presentación primero. Eventualmente te darás cuenta de que estás pasando demasiados accesorios por los componentes intermedios. Cuando observa que algunos componentes no usan los accesorios que reciben, sino que simplemente los reenvían hacia abajo y tiene que volver a cablear todos esos componentes intermedios en cualquier momento en que los niños necesiten más datos, es un buen momento para introducir algunos componentes contenedores. De esta manera, puede obtener los datos y los apoyos de comportamiento a los componentes de la hoja sin sobrecargar los componentes no relacionados en el medio del árbol.

Este es un proceso continuo de refactorización, así que no intentes hacerlo bien la primera vez. A medida que experimentes con este patrón, desarrollarás un sentido intuitivo para cuándo es el momento de extraer algunos contenedores, al igual que sabes cuándo es el momento de extraer una función. ¡Mi serie gratuita Redux Egghead también puede ayudarte con eso!

Otras dicotomías

Es importante que entienda que la distinción entre los componentes de presentación y los contenedores no es técnica. Más bien, es una distinción en su propósito.

Por el contrario, aquí hay algunos relacionados (¡pero diferentes!) distinciones técnicas:

  • Con Estado y sin estado. Algunos componentes usan el método React setState () y otros no. Mientras que los componentes contenedores tienden a tener estado y los componentes de presentación tienden a ser sin estado, esta no es una regla dura. Los componentes de presentación pueden tener estado y los contenedores también pueden ser sin estado.
  • Clases y Funciones. Desde React 0.14, los componentes se pueden declarar tanto como clases como como funciones. Los componentes funcionales son más fáciles de definir, pero carecen de ciertas características que actualmente solo están disponibles para los componentes de clase. Algunas de estas restricciones pueden desaparecer en el futuro, pero existen hoy en día. Debido a que los componentes funcionales son más fáciles de entender, le sugiero que los use a menos que necesite estados, ganchos de ciclo de vida u optimizaciones de rendimiento, que solo están disponibles para los componentes de clase en este momento.
  • Puro e impuro. La gente dice que un componente es puro si se garantiza que devuelve el mismo resultado con los mismos accesorios y el mismo estado. Los componentes puros se pueden definir como clases y funciones, y pueden ser tanto con estado como sin estado. Otro aspecto importante de los componentes puros es que no dependen de mutaciones profundas en props o state, por lo que su rendimiento de renderizado puede optimizarse mediante una comparación superficial en su gancho shouldComponentUpdate (). Actualmente solo las clases pueden definir shouldComponentUpdate (), pero eso puede cambiar en el futuro.

Tanto los componentes de presentación como los contenedores pueden caer en cualquiera de esos cubos. En mi experiencia, los componentes de presentación tienden a ser funciones puras sin estado, y los contenedores tienden a ser clases puras con estado. Sin embargo, esto no es una regla, sino una observación, y he visto los casos exactamente opuestos que tenían sentido en circunstancias específicas.

No tome la separación de componentes de presentación y contenedor como un dogma. A veces no importa o es difícil trazar la línea. Si no está seguro de si un componente específico debe ser presentacional o un contenedor, podría ser demasiado pronto para decidir. ¡No te preocupes!

Ejemplo

Este gist de Michael Chan prácticamente lo clava.

Más información

  • Primeros pasos con Redux
  • Los Mixins están muertos, Composición Viva
  • Componentes de contenedores
  • Diseño Web Atómico
  • Creación de la Fuente de Noticias de Facebook con Relé

Notas al pie

* En una versión anterior de este artículo, los llamé componentes “inteligentes” y “tontos”, pero esto fue demasiado duro para los componentes de presentación y, lo más importante, realmente no explicó la diferencia en su propósito. Disfruto mucho mejor de los nuevos términos, ¡y espero que tú también!

* * En una versión anterior de este artículo, afirmé que los componentes de presentación solo deben contener otros componentes de presentación. Ya no creo que este sea el caso. Si un componente es un componente de presentación o un contenedor es su detalle de implementación. Debería poder reemplazar un componente de presentación con un contenedor sin modificar ninguno de los sitios de llamadas. Por lo tanto, tanto los componentes de presentación como los de contenedor pueden contener otros componentes de presentación o contenedor perfectamente.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.