React Slots: una Nueva Forma de Composición

Rate this content
Bookmark

En esta charla aprenderemos qué son los Slots y qué significa para el ecosistema de React, cuál es el estado actual y el futuro.

21 min
24 Oct, 2022

Video Summary and Transcription

La charla de hoy presenta React Slots, una nueva forma de composición para sistemas de diseño. La forma de configuración proporciona flexibilidad pero puede llevar a casos de uso no controlados y patrones incorrectos. Se creó el RFC de React Slots para abordar las limitaciones del soporte de React para componentes web y slots. Introduce las APIs createHost y createSlot para permitir la composición de componentes y resolver problemas anteriores. React Slots RFC permite estilos flexibles de componentes y la creación de estructuras complejas sin renderizarlas en el navegador.

Available in English

1. Introducción a React Snots y Diseño de API

Short description:

Hoy, mi tema es React Snots, una nueva forma de composición. Cada vez que encuentro un nuevo sistema de diseño, lo primero que hago es ver cómo implementan el componente de entrada de texto. La solución es simple. Podemos pasar el nombre de la clase y el estilo al contenedor del componente en su lugar. Similar a WrapRef, podemos introducir indicaciones para el contenedor, indicaciones para la etiqueta y indicaciones para la descripción. Aquí está la API del componente de entrada de texto de Man Time.

¡Hola, es un gran honor estar aquí para compartir con ustedes algunos de mis pensamientos sobre el sistema de diseño! Mi nombre es Gongwu Nie, pueden llamarme Neo. Hoy, mi tema es React Snots, una nueva forma de composición.

Antes de adentrarnos en el tema, me gustaría contar la historia primero. Cuando trabajo en el sistema de diseño, siempre me pregunto, ¿cómo construir componentes flexibles y a prueba de futuro? Para mí, lo más difícil no es crear nuevos componentes o solucionar errores extraños. Es el diseño de la API del componente.

Cada vez que encuentro un nuevo sistema de diseño, lo primero que hago es ver cómo implementan el componente de entrada de texto, porque es uno de los componentes más misteriosos. Permítanme mostrarles. El componente de entrada de texto es simple y directo. Viene con una etiqueta, un campo de entrada y tiene una prueba. Primero agreguemos soporte de accesibilidad. Al construir un componente compartible, por favor no olviden reenviar la referencia. Necesitamos la referencia al campo de entrada para enfocarlo en la validación del formulario. Pero, ¿qué pasa con el contenedor? También necesitamos la referencia al contenedor para adjuntar un popover o tooltip en algunos casos. Bueno, podemos agregar un contenedor para ello.

Pero esperen, ¿han notado un problema potencial con el enfoque actual? ¿Qué sucederá si intentamos agregar márgenes al componente desde otro componente? Aumentará el margen entre la etiqueta, el campo de entrada y la descripción, porque estamos propagando todas las demás indicaciones al elemento de entrada interno. La solución es simple. Podemos pasar el nombre de la clase y el estilo al contenedor del componente en su lugar. ¿Se ve bien? El problema es que el componente se vuelve confuso para los consumidores. ¿Qué indicación se pasará al contenedor? ¿Qué indicación se pasará al campo de entrada? El componente se convierte en una caja negra. En realidad, el equipo de producto seguirá pidiendo más opciones para acceder a los elementos internos, como adjuntar eventos de punto o agregar atributos de datos a la etiqueta o descripción. Similar a WrapRef, podemos introducir indicaciones para el contenedor, indicaciones para la etiqueta y indicaciones para la descripción. Funciona. Pero no termina aquí. ¿Qué pasa si necesitamos agregar elementos alrededor del campo de entrada, más indicaciones? Ahora pueden ver cómo la API se vuelve abultada con este enfoque. Aquí está la API del componente de entrada de texto de Man Time. No me malinterpreten. Man Time es una gran biblioteca de componentes. Me encanta mucho.

2. Forma de configuración y composición de componentes

Short description:

Eligen la forma de configuración para diseñar la API del componente. En la forma de configuración, tenemos que admitir flexibilidad con un aumento de la API y los componentes se convierten en una caja negra completa para los consumidores. Retrocedamos un paso y pensemos, ¿cómo construimos nuestra aplicación web en React? Componemos componentes. Cada componente hace su propio trabajo y eso es todo. Simple y flexible.

Eligen la forma de configuración para diseñar la API del componente. En la forma de configuración, tenemos que admitir flexibilidad con un aumento de la API y los componentes se convierten en una caja negra completa para los consumidores.

Retrocedamos un paso y pensemos, ¿cómo construimos nuestra aplicación web en React? Componemos componentes. Cada componente hace su propio trabajo y eso es todo. Simple y flexible.

Entonces, ¿qué pasa si usamos el mismo enfoque para los componentes compartibles? Obtenemos la misma claridad, simplicidad y flexibilidad. Muchas bibliotecas populares de componentes utilizan el enfoque de composición para implementar componentes accesibles como Chakra UI, Redux primitives, Hedonist UI y más.

Para admitir la accesibilidad, tenemos que usar el Contexto de React para comunicarnos entre el padre y los hijos y coordinar los atributos de accesibilidad. La configuración es fácil de usar. Realmente quieres escribir tu módulo en el estilo de la izquierda en lugar del estilo de la derecha. Pero el enfoque de composición no es la respuesta final.

3. Component Consistency and Flexibility

Short description:

Tomemos Chakra UI como ejemplo. ¿Qué pasa si intercambiamos la posición de inputLeftAddon e inputRightAddon? Obtendremos inputLeftAddon mostrado en el lado derecho e inputRightAddon mostrado en el lado izquierdo. Construyendo una Lista Accesible, los padres necesitan conocer la información de los hijos para que cumpla con la accesibilidad. La forma de configuración proporciona la mejor consistencia, ya que el componente es la única fuente de verdad. La forma de composición proporciona la mejor flexibilidad, pero conduce a casos de uso no controlados y patrones incorrectos. Los slots son el estándar para los componentes web, lo que te permite definir espacios reservados que pueden ser llenados con cualquier fragmento de marcado que desees.

Tomemos Chakra UI como ejemplo. ¿Qué pasa si intercambiamos la posición de inputLeftAddon e inputRightAddon? Obtendremos inputLeftAddon mostrado en el lado derecho e inputRightAddon mostrado en el lado izquierdo. Esto rompe la semántica con un estilo roto. Tengo un pasatiempo cuando encuentro un nuevo sistema de diseño, que es probar la resonancia de los componentes. Al agregar nodos adicionales a los elementos, vemos cómo se rompen. Para un sistema de diseño dedicado, entregamos componentes bien diseñados. Pero no puedes imaginar cómo los desarrolladores alternativos los romperán de diversas formas y, desafortunadamente, no podemos evitar que lo hagan.

Dirías que no importa si seguimos el orden de diseño correctamente. Bueno, veamos otro problema más realista. Construyendo una Lista Accesible, los padres necesitan conocer la información de los hijos para que cumpla con la accesibilidad. Es fácil lograrlo utilizando la forma de configuración, ya que el padre conoce todos los elementos desde ItemPrompt. Pero es un poco engorroso para la forma de composición. El menú no puede ver sus elementos internos. El componente está ciego. Para resolver el problema, podemos usar react-children con react-clone-element. Luego podemos tomar el control de la renderización de los elementos en el componente padre. Pero en términos de extensión, volverá a romperse. Incluso si podemos iterar los hijos, el padre sigue estando ciego ya que no puede ver los detalles profundos. El problema está bien descrito por root UI, si estás interesado, aquí tengo una tarea para ti para que descubras cómo estas bibliotecas están tratando de resolver este problema.

Recapitulemos, la forma de configuración proporciona la mejor consistencia, ya que el componente es la única fuente de verdad, pero es difícil de extender y se convierte en una caja negra cuando se usan múltiples elementos. Por el contrario, la forma de composición proporciona la mejor flexibilidad, puedes personalizar tus subcomponentes libremente, pero causa otro problema, la consistencia, conduce a casos de uso no controlados y patrones incorrectos. Entonces, ¿podemos tener una forma de construir componentes con flexibilidad manteniendo la consistencia? Sí, la respuesta es no. Los slots son el estándar para los componentes web. En los componentes web, los slots se identifican por su atributo de nombre y te permiten definir espacios reservados en tus plantillas que pueden ser llenados con cualquier fragmento de marcado que desees cuando se utiliza el elemento en el marcado. Es más fácil entender el concepto en el código. Primero, definimos una plantilla con algunos espacios reservados con nombre y definimos el componente web. Luego llenamos los espacios reservados con slots con nombre. Finalmente, obtenemos el resultado con los elementos inyectados. Aquí puedes ver cómo se garantiza la consistencia. El diseño se define en la plantilla, no se describe por el orden de composición. Algunos frameworks populares como Vue y Svelte también implementaron el patrón de composición de slots a nivel de framework de manera similar.

4. React Slots RFC y los Desafíos

Short description:

React no admite bien los componentes web y los slots. Se han probado varios enfoques, como usar react-children con react-clone-element, pero tienen limitaciones. React Spectrum utiliza contexto y orden de cuadrícula, pero tiene funcionalidad limitada. GitHub Primer utiliza renderizado doble, pero no admite el renderizado en el lado del servidor. Se creó un paquete experimental llamado React-core-return que parecía prometedor, pero fue eliminado. Por lo tanto, se creó React Slots RFC para abordar estos problemas.

Pero como sabes, React todavía no admite muy bien los componentes web, por no mencionar los slots. Hay muchos enfoques de la comunidad que intentan llevar los slots al mundo de React. El enfoque más común es usar react-children con react-clone-element. Pero no escala muy bien ya que el componente está ciego. React Spectrum utiliza contexto y orden de cuadrícula para resolver el problema del desorden, pero la funcionalidad es limitada. Por ejemplo, con el orden de cuadrícula, cambiamos el índice de tipo de manera inesperada. GitHub Primer utiliza el renderizado doble para abordar los slots. Renderiza los subcomponentes en un navegador con contenido vacío y recopila la información del slot primero, y luego utiliza el slot en el segundo renderizado. El problema es evidente. No admite el renderizado en el lado del servidor. Hubo un paquete experimental del equipo principal de React llamado React-core-return, que proporciona una forma de interpolar los hijos durante la fase de renderizado. Podría ser el mejor candidato para llevar los slots a React, pero desafortunadamente, fue eliminado poco después. Así que creé React Slots RFC para describir los problemas con la propuesta. Permíteme mostrarte el código directamente.

5. React Slots RFC y Composición de Componentes

Short description:

Nuevamente, el componente de entrada de texto típico implementado en React Slots RFC. Introdujimos dos nuevas APIs llamadas createHost y createSlot, similares a React call return pero con un modelo mental más simple. createHost crea la plantilla y createSlot crea espacios reservados, lo que nos permite interactuar con los elementos. Esto abre nuevas posibilidades para la composición de componentes y proporciona una solución a problemas anteriores. Ahora podemos demostrar cómo React Slots RFC resuelve estos problemas y admite accesibilidad, flexibilidad y resistencia de componentes.

Nuevamente, el componente de entrada de texto típico implementado en React Slots RFC. En el RFC, introdujimos dos nuevas APIs llamadas createHost y createSlot, que son muy similares a React call return pero con un modelo mental mucho más simple. createHost crea la plantilla y createSlot crea espacios reservados, y luego se compone el Slot en el componente host. Es bastante similar a Slot para componentes web, pero mucho más poderoso, ya que no simplemente inyectamos los elementos, los interactuamos.

Abre el tercer ojo del componente, ahora el padre puede ver los detalles profundos de sus hijos, sin importar cómo se hayan extendido. Ahora, es hora de la demostración. Te mostraré cómo los problemas anteriores se resolverán perfectamente con React Slots RFC. Aquí, implementé React Slots RFC con react-core-return en 10 líneas. Y luego, el campo de texto, primero, creamos los slots para la etiqueta, el input y la etiqueta. Pasamos los hijos a createHost, luego nos da los slots. Aquí puedes ver cómo podemos interpolar los slots. Eso significa que podemos hacer todo lo que queramos en un solo lugar. Aquí puedes ver cómo admito accesibilidad para la entrada de texto. Podemos leer directamente el ID del input para la etiqueta, y también podemos iterar todo el texto.

Ahora, te mostraré algo de magia. No importa cómo componga los slots, no cambia el resultado porque el diseño está definido en la plantilla por createHost. Mientras tanto, aún somos libres de extender los slots. Por ejemplo, extendemos la etiqueta, extendemos el input, y podemos cambiar el orden de la etiqueta. Cambiará el resultado porque es una lista. Y el otro problema es la resistencia del componente. Permíteme intentar envolver la etiqueta con un nodo adicional. Funcionará porque no es un nodo. Eso es muy importante para un sistema de diseño dedicado, porque hemos preparado un muy... Hemos preparado los componentes. No deberíamos cambiar el diseño fácilmente. Volvámoslo a cambiar. Otro caso de uso es que no importa lo que usemos, no está fuera del host. Nada se renderizará. Eso también es importante para un sistema de diseño consistente. Los slots anidados también son compatibles.

6. React Slots RFC y Flexibilidad de Componentes

Short description:

React Slots RFC nos permite crear campos de entrada de texto sin la necesidad de etiquetas o inputs estilizados. En su lugar, los estilizamos en la plantilla. El slot actúa como un portador de datos, lo que nos permite crear estructuras complejas como árboles sin renderizarlos en el navegador. Aún podemos acceder a los datos y beneficiarnos de las características de React, como los métodos del ciclo de vida y el contexto.

¿Has notado cómo creamos los campos de entrada de texto, no necesitamos crear una etiqueta estilizada para el campo de texto o un input para el campo de texto. En su lugar, lo estilizamos en la plantilla. El slot en sí no renderiza nada, solo actúa como un portador de datos. Eso significa mucho. Por ejemplo, podemos crear un generador de árboles. Aquí tienes un ejemplo. Creamos un árbol, pero no se renderiza en el navegador. Pero puedes verlo en la consola. Aquí está el árbol, el menú anidado, pero así es como los componemos. Pero no se renderiza en el navegador en absoluto. Aún así, podemos obtener data, porque el slot es solo un portador de data. No es necesario renderizarlo en el navegador en absoluto. Y puedes ver cómo es reactivo. O eliminar el menú anidado. Así que aún podemos beneficiarnos de todo lo que React nos proporciona. Los ciclos de vida, el estado, el contexto, y todas las demás cosas. Hay un paquete llamado React New. Intenta hacer lo mismo, pero veamos el tamaño. Es casi 100 KB minimizado, incluso 30 KB minimizado, y CCPT hace lo mismo porque tiene que incluir el reconciliador de React en él. Pero con React-SNOS podemos usar el reconciliador de React directamente. Ahora puedes ver cómo logramos flexibilidad manteniendo la consistencia en React-SNOS-RFC con un modelo de personalización descentralizada y control centralizado. ¿Qué significa eso para nosotros? Ahora, el componente host es la única fuente de verdad y toma el control de sus hijos, como en el enfoque de configuración. Así que podemos hacer que los componentes componibles sean predecibles. Puedes ver lo simple que es agregar soporte de accesibilidad. Y como no es necesario renderizar los slots en un árbol DOM, en su lugar simplemente conectamos la información y luego decidimos qué renderizar en función de la información conectada. Por lo tanto, el soporte de virtualización está listo para usar y hay más posibilidades, por ejemplo, un renderizador personalizado. Además, creé un paquete llamado create-slots que implementa completamente el RFC de react-slots, a diferencia de otros enfoques que no funcionan bien con algunas características de React, como el renderizado en el lado del servidor. Utilicé el pre-renderizado, que es similar a react-call-return, para recopilar la información de los hijos durante la fase de renderizado y utilizar la información más adelante durante la misma fase de renderizado, y luego podemos confirmar el resultado interpolado en el navegador. Y ya se ha utilizado en el sistema de diseño de Revolut. Como también estamos utilizando el enfoque de composición para construir nuestros componentes compartidos, tenemos casi 200 componentes compartidos y nos enfrentamos a más problemas de los que he discutido aquí, lo que finalmente me llevó a esta charla. Pero el paquete no es ideal, ya que repite el trabajo del reconciliador de React. Por eso todavía quiero ver el soporte de React mismo. Y eso es todo. Si quieres discutir más, puedes encontrarme en GitHub y Twitter. Gracias.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Top Content
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
React Advanced Conference 2023React Advanced Conference 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
React provides a contract to developers- uphold certain rules, and React can efficiently and correctly update the UI. In this talk we'll explore these rules in depth, understanding the reasoning behind them and how they unlock new directions such as automatic memoization. 
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Top Content
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
React Advanced Conference 2021React Advanced Conference 2021
27 min
(Easier) Interactive Data Visualization in React
Top Content
If you’re building a dashboard, analytics platform, or any web app where you need to give your users insight into their data, you need beautiful, custom, interactive data visualizations in your React app. But building visualizations hand with a low-level library like D3 can be a huge headache, involving lots of wheel-reinventing. In this talk, we’ll see how data viz development can get so much easier thanks to tools like Plot, a high-level dataviz library for quick & easy charting, and Observable, a reactive dataviz prototyping environment, both from the creator of D3. Through live coding examples we’ll explore how React refs let us delegate DOM manipulation for our data visualizations, and how Observable’s embedding functionality lets us easily repurpose community-built visualizations for our own data & use cases. By the end of this talk we’ll know how to get a beautiful, customized, interactive data visualization into our apps with a fraction of the time & effort!

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Advanced Conference 2021React Advanced Conference 2021
132 min
Concurrent Rendering Adventures in React 18
Top Content
Featured WorkshopFree
With the release of React 18 we finally get the long awaited concurrent rendering. But how is that going to affect your application? What are the benefits of concurrent rendering in React? What do you need to do to switch to concurrent rendering when you upgrade to React 18? And what if you don’t want or can’t use concurrent rendering yet?

There are some behavior changes you need to be aware of! In this workshop we will cover all of those subjects and more.

Join me with your laptop in this interactive workshop. You will see how easy it is to switch to concurrent rendering in your React application. You will learn all about concurrent rendering, SuspenseList, the startTransition API and more.
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn