
Escrito por Kristofer Selbekk , en colaboración con Caroline Odden . Basado en una conferencia con el mismo nombre y las mismas personas en la reunión de ReactJS en Oslo en junio de 2019.
Del traductor: el nombre original de The 10 Component Commandments no menciona React, pero la mayoría de los ejemplos y recomendaciones se relacionan específicamente con la reacción, además, el artículo se presenta bajo la etiqueta react y los desarrolladores escribieron la reacción .
No es fácil crear componentes que usarán muchos desarrolladores. Debe considerar cuidadosamente qué accesorios usar si estos accesorios son parte de la API pública.
En este artículo, haremos una breve introducción a algunas de las mejores prácticas para desarrollar la API en su conjunto, así como a formar diez mandamientos que puede usar para crear componentes que sus colegas desarrolladores estarán encantados de usar.

¿Qué es una API?
Una API - o interfaz de programación de aplicaciones - es donde se encuentran dos piezas de código. Esta es la superficie de contacto entre su código y el resto del mundo. Llamamos a esta superficie una interfaz. Este es un conjunto específico de acciones o puntos de datos con los que puede interactuar.
La interfaz entre la clase y el código que llama a esta clase también es una API. Puede llamar a los métodos de la clase para recibir datos o ejecutar las funciones incluidas en él.
Siguiendo el mismo principio, los accesorios que acepta su componente, esta es su API . Esta es la forma en que los desarrolladores interactúan con su componente.
Algunas mejores prácticas de diseño de API
Entonces, ¿qué reglas y consideraciones se aplican al desarrollar una API? Bueno, investigamos un poco y resultó que hay muchos recursos excelentes sobre este tema. Elegimos dos - Josh Tauberer - "¿Qué hace una buena API?" y un artículo de Ron Kurir con el mismo título , y llegó a estas cuatro prácticas.
Versiones estables
Una de las cosas más importantes a tener en cuenta al crear una API es mantenerla lo más estable posible. El número de cambios críticos debe ser mínimo. Si tiene que hacer cambios críticos, asegúrese de escribir guías de actualización detalladas y, si es posible, escriba un código de modificación que automatice este proceso para los desarrolladores.
Mensajes de error descriptivos
Siempre que ocurra un error al llamar a su API, debe hacer todo lo posible para explicar qué salió mal y cómo solucionarlo. Si regaña al usuario con mensajes como "mal uso" y no da ninguna explicación, su API dejará una mala impresión.
En su lugar, escriba errores descriptivos que ayuden al usuario a corregir cómo usan su API.
Minimice las sorpresas para los desarrolladores.
Los desarrolladores son criaturas frágiles, y no debes asustarlos cuando usan tu API. En otras palabras, haga que su API sea lo más intuitiva posible. Lo logrará si sigue las mejores prácticas y las convenciones de nomenclatura existentes.
Además, su código siempre debe ser coherente. Si usa los nombres lógicos de propiedades con is
o has
en un lugar, pero los omite aún más, esto confundirá a las personas.
Minimizar la superficie API
Tu API también necesita ser minimizada. Muchas características son geniales, pero cuanto más pequeña sea la superficie de su API (superficie API), menos desarrolladores tendrán que estudiarla para comenzar a trabajar productivamente con ella. ¡Gracias a esto, su API será percibida como fácil de usar!
Siempre hay una manera de controlar el tamaño de sus API. Uno de ellos está refactorizando la nueva API de la anterior.
Los diez mandamientos para componentes web

Entonces, estas cuatro reglas de oro funcionan bien para la API REST y para las antiguas piezas de procedimiento en Pascal, pero ¿cómo transferirlas al mundo moderno de React?
Como dijimos anteriormente, los componentes tienen su propia API. Los llamamos props
, y es con su ayuda que los datos se transfieren a los componentes. ¿Cómo estructuramos los accesorios para no violar ninguna de las reglas anteriores?
Hemos creado esta lista de diez reglas de oro que se siguen mejor al crear sus componentes. Esperamos que te sean útiles.
1. Documentar el uso de componentes.
Si la forma en que desea utilizar su componente no está documentada, entonces este componente es inútil. Bueno, casi inútil, siempre puedes ver su implementación, pero a pocas personas les gusta hacer esto.
Hay muchas formas de documentar sus componentes, pero le recomendamos que preste atención a estos tres:
Los dos primeros le brindan un lugar para trabajar al desarrollar sus componentes, y el tercero le permite escribir documentación de forma gratuita utilizando MDX
No importa lo que elija, siempre documente tanto la API en sí misma como cómo y cuándo deben usarse sus componentes . La última parte es crítica en las bibliotecas de uso general: para que las personas utilicen correctamente un botón o una cuadrícula de diseño en un contexto determinado.
2. Habilite la semántica contextual
HTML es un lenguaje para estructurar información de forma semántica. Solo aquí, la mayoría de nuestros componentes consisten en etiquetas <div />
. Esto tiene sentido: los componentes universales no pueden saber de antemano cuáles serán, tal vez <article />
, o <section />
, o <aside />
-, pero esta situación está lejos de ser ideal.
Hay otra opción, simplemente dejar que sus componentes acepten accesorios as
, y así determinar qué elemento DOM se representará. Aquí hay un ejemplo de cómo implementar esto:
function Grid({ as: Element, ...props }) { return <Element className="grid" {...props} /> } Grid.defaultProps = { as: 'div', };
Cambiamos el nombre de prop por la variable Element
y la usamos en nuestro JSX. Le damos un valor div
predeterminado común si no tenemos que pasar una etiqueta HTML más semántica.
Cuando llegue el momento de usar el componente <Grid />
, simplemente puede pasar la etiqueta correcta:
function App() { return ( <Grid as="main"> <MoreContent /> </Grid> ); }
Esto también funciona con los componentes React. Por ejemplo, si desea que el componente <Button />
represente el React Router <Link />
:
<Button as={Link} to="/profile"> Go to Profile </Button>
3. Evita los accesorios booleanos
Los accesorios lógicos son, como, una buena idea. Se pueden usar sin valor, por lo que se ve muy elegante:
<Button large>BUY NOW!</Button>
Pero aunque se ve bien, las propiedades lógicas solo permiten dos posibilidades. Encendido o apagado Visible u oculto. 1 o 0.
Cada vez que comienzas a introducir propiedades lógicas para cosas como el tamaño, las opciones, los colores o cualquier cosa que no sea una elección binaria, tienes problemas.
<Button large small primary disabled secondary> ?? </Button>
En otras palabras, las propiedades lógicas a menudo no se escalan con los requisitos cambiantes. En cambio, para valores que pueden convertirse en algo más que una selección binaria, es mejor usar valores enumerados, como cadenas.
<Button variant="primary" size="large"> </Button>
Esto no significa que las propiedades lógicas no puedan utilizarse en absoluto. Usted puede! El accesorio disabled
, que enumeré anteriormente, aún debería ser lógico, porque no hay un estado medio entre encendido y apagado. Simplemente deje las propiedades booleanas solo para una elección verdaderamente binaria.
4. Usa props.children
React tiene algunas propiedades especiales que se tratan de manera diferente a las demás. Se necesita una de estas key
para rastrear el orden de los elementos de la lista. Y otro de esos accesorios especiales son los children
.
Todo lo que coloque entre la etiqueta de apertura y cierre del componente se coloca dentro de la props.children
. Y debe usar esto con la mayor frecuencia posible.
Por qué Porque es mucho más fácil que tener content
apoyo para contenido o algo así que generalmente solo toma valores simples, como el texto.
<TableCell content="Some text" /> // <TableCell>Some text</TableCell>
El uso de props.children
para props.children
tiene varias ventajas. En primer lugar, esto es similar a cómo funciona el HTML normal. En segundo lugar, ¡puedes transferir libremente lo que quieras! En lugar de agregar accesorios como leftIcon
y rightIcon
a su componente, simplemente props.children
como parte del props.children
:
<TableCell> <ImportantIcon /> Some text </TableCell>
Puede argumentar que su componente solo necesita representar texto plano, y en algunos casos lo es. Hasta cierto punto. Al usar props.children
, usted garantiza que su API estará lista para los requisitos cambiantes.
5. Deje que el padre se aferre a la lógica interna
A veces creamos componentes con mucha lógica interna y estados, por ejemplo, diagramas autocompletados o interactivos.
Tales componentes a menudo sufren de API excesivas, una de las razones es el gran número de casos de uso diferentes que se acumulan con el desarrollo del proyecto.
Pero, ¿qué pasaría si pudiéramos proporcionar un accesorio único y estandarizado que permita al desarrollador controlar, responder o simplemente cambiar el comportamiento predeterminado del componente?
Kent Dodds escribió un excelente artículo sobre el concepto de reductores estatales. Aquí hay un artículo sobre el concepto en sí , y también, aquí hay un artículo sobre cómo implementar esto para los ganchos React .
En resumen, este es un patrón de transferencia de función reductor de estado a su componente, que permitirá al desarrollador acceder a todas las acciones realizadas dentro de su componente. Puede cambiar de estado o incluso causar efectos secundarios. Esta es una excelente manera de proporcionar un alto nivel de personalización, sin ningún accesorio .
Así es como podría verse:
function MyCustomDropdown(props) { const stateReducer = (state, action) => { if (action.type === Dropdown.actions.CLOSE) { buttonRef.current.focus(); } }; return ( <> <Dropdown stateReducer={stateReducer} {...props} /> <Button ref={buttonRef}>Open</Button> </> }
Por cierto, puede crear formas más simples de responder a los eventos. Es probable que usar el onClose
en el ejemplo anterior haga que el uso del componente sea más conveniente. Use el patrón "reductor de estado" cuando sea necesario.
6. Use el operador de propagación para los accesorios restantes
Cada vez que cree un nuevo componente, asegúrese de aplicar los puntos suspensivos a los accesorios restantes y enviarlos al elemento para el que tiene sentido.
No es necesario que continúe agregando accesorios a su componente, que simplemente se pasará al componente o elemento base. Esto hará que su API sea más estable al eliminar la necesidad de muchos errores de versiones pequeñas cuando el próximo desarrollador necesite un nuevo detector de eventos o una etiqueta ARIA.
Puedes hacerlo así:
function ToolTip({ isVisible, ...rest }) { return isVisible ? <span role="tooltip" {...rest} /> : null; }
Siempre que su componente pase prop a su implementación, como un nombre de clase o un controlador onClick
, asegúrese de que otro desarrollador pueda hacer lo mismo. En el caso de una clase, simplemente puede agregar la clase prop utilizando la conveniente biblioteca de nombres de clase npm (o simplemente concatenación de cadenas):
import classNames from 'classnames'; function ToolTip(props) { return ( <span {...props} className={classNames('tooltip', props.tooltip)} /> }
En el caso de los controladores de clics y otras devoluciones de llamada, puede combinarlos en una función utilizando una pequeña utilidad. Aquí hay una forma de hacer esto:
function combine(...functions) { return (...args) => functions .filter(func => typeof func === 'function') .forEach(func => func(...args)); }
Aquí creamos una función que acepta una lista de funciones para combinarlas. Devuelve una nueva devolución de llamada, que los llama a todos a su vez con los mismos argumentos.
Esta función se puede usar de esta manera:
function ToolTip(props) { const [isVisible, setVisible] = React.useState(false); return ( <span {...props} className={classNames('tooltip', props.className)} onMouseIn={combine(() => setVisible(true), props.onMouseIn)} onMouseOut={combine(() => setVisible(false), props.onMouseOut)} /> ); }
7. Use los valores predeterminados
Asegúrese de dar suficientes valores predeterminados (valores predeterminados) a sus accesorios. Por lo tanto, reducirá el número de accesorios obligatorios. Esto simplificará enormemente su API.
Tome, por ejemplo, el controlador onClick
. Si su código no necesita este controlador, use la función vacía (noop-function) como accesorio por defecto. De esta manera, puede llamarlo en su código como si siempre se pasara.
Otro ejemplo podría ser para la entrada del usuario. Suponga que la cadena de entrada es una cadena vacía a menos que se especifique lo contrario. Esto le permitirá asegurarse de que siempre está tratando con un objeto de cadena, no con algo indefinido o nulo.
8. No es necesario cambiar el nombre de los atributos HTML
HTML como lenguaje tiene sus propios accesorios, o atributos, y en sí mismo es una API para elementos HTML. Entonces, ¿por qué no seguir usando esta API?
Como mencionamos anteriormente, minimizar la superficie API y su intuición son métodos útiles para mejorar la API de sus componentes. Entonces, en lugar de crear su propio accesorio screenReaderLabel
, ¿por qué no simplemente usar una aria-label
existente?
Manténgase alejado de renombrar cualquier atributo HTML existente para su propia "facilidad de uso". Ni siquiera reemplaza la API existente, simplemente agrega la suya encima. La gente todavía puede pasar la aria-label
junto con su screenReaderLabel
screenReaderLabel, y ¿cuál debería ser el valor final entonces?
Además, asegúrese de nunca anular los atributos HTML en sus componentes. Un gran ejemplo es el atributo de type
del elemento <button />
. Se puede submit
(predeterminado), button
o reset
. Sin embargo, muchos desarrolladores redefinen este accesorio para denotar el tipo visual del botón ( primary
, cta
, etc.).
Si va a utilizar dicho accesorio, deberá agregar una anulación para el atributo de type
verdadero. Esto generará confusión, dudas y molestias por parte de los desarrolladores.
Créame, cometí este error una y otra vez, si lo comete, tendrá que desenredarlo durante mucho tiempo.
9. Escribe los tipos de accesorios (o solo tipos)
Ninguna documentación será tan buena como la documentación que se encuentra dentro de su código. React viene con una excelente manera de declarar sus API usando el paquete prop-types
. Úsalo.
Puede especificar los requisitos de formato para sus accesorios obligatorios y opcionales, y puede mejorarlos con comentarios JSDoc .
Si no especifica un accesorio obligatorio o pasa un valor no válido o inesperado, en el tiempo de ejecución recibirá una advertencia en la consola. Esto ayuda mucho durante el desarrollo y puede eliminarse de la producción.
Si escribe sus aplicaciones React en TypeScript o usa Flow, obtendrá la documentación de la API como una función de lenguaje. Esto mejora aún más el soporte de las herramientas de desarrollo y simplifica el trabajo.
Si usted mismo no utiliza JavaScript escrito, debería considerar proporcionar definiciones de tipo a los desarrolladores que lo utilizan. Entonces será mucho más fácil para ellos usar sus componentes.
10. Diseño para desarrolladores.
Finalmente, la regla más importante a seguir. Asegúrese de que su API y su trabajo con sus componentes estén optimizados para los desarrolladores que lo usarán.
Una forma de simplificar el trabajo de un desarrollador es darle comentarios sobre el uso inapropiado. Haga esto con mensajes de error y también, pero solo durante el desarrollo, con advertencias de que hay formas más eficientes de usar su componente.
Al escribir errores y advertencias, proporcione enlaces a su documentación o muestre ejemplos de código simples. Cuanto más rápido entienda el desarrollador cuál es el problema y cómo solucionarlo, más conveniente será su componente para el trabajo.
Increíblemente, pero resultó que la presencia de todas estas advertencias de error no afecta el tamaño del paquete final. Gracias a los milagros de eliminar el código muerto, todo este texto y código de error se pueden eliminar durante el ensamblaje en producción.
Una de las bibliotecas que ofrece comentarios increíblemente buenos es React. No importa si olvidó especificar la clave para los elementos de la lista, o escribió el método del ciclo de vida incorrectamente, o tal vez olvidó extender la clase base o llamó al gancho de una manera incierta; en cualquier caso, recibirá grandes mensajes de error en la consola. ¿Por qué los desarrolladores que usan sus componentes deben esperar menos de usted?
Así que diseña para tus futuros usuarios. Diseña para ti desde el futuro. ¡Diseñe para los desafortunados que tendrán que mantener su código cuando se vaya! Diseño para desarrolladores.
Total
Podemos aprender mucho del enfoque clásico de API. Siguiendo los consejos, trucos, reglas y mandamientos de este artículo, puede crear componentes que sean fáciles de usar, fáciles de mantener, intuitivos y, si es necesario, muy flexibles.