
Guía sobre el patrón Control Props en React JS 2025

Juan Correa
Desarrollador de Software Senior
El patrón Control Props es uno de los patrones de diseño avanzados en React.js que te permiten crear componentes aún más flexibles y controlables, dándote el poder de controlar su estado desde fuera. Veamos cómo funciona y por qué es tan útil.
Table of Contents
¿Qué son los Control Props?
Este patrón está inspirado en la manera en que funcionan los formularios controlados.
Un formulario controlado es aquel cuyos valores son controlados por React usando un estado interno e indicando la manera en que ese estado debe actualizarse. Por ejemplo:
<input value={inputVal} onChange={handleChange} />
Ahora imagina poder replicar esta lógica pero en cualquier componente, no solo en formularios. En esto consiste este patrón.
Por lo tanto, podemos afirmar que este patrón permite a los usuarios de tu componente controlar el estado de la UI a través de accesos de control.
Nota: con "usuarios" me refiero a los componentes que usan el componente.
¿Quieres dominar los Patrones de Diseño en React.js?
En mi ebook "Patrones avanzados en React.js", encontrarás más información sobre los patrones explicados en este post y contenido de alta calidad que te ayudará a llevar tus habilidades al siguiente nivel.
Descargar ebook gratisVentajas y desventajas de Control Props
Las principal ventaja de este patrón es:
- Una manera muy sencilla de dar la opción de delegar el control del estado a los usuarios de tu componente para personalizar la lógica de actualización de estado. Podemos afirmar que deja el manejo de estado abierto a su extensión y cerrado a su modificación (Principio Abierto - Cerrado).
La principal desventaja es:
- En caso de que el componente consumidor quiera controlar nuestro componente, debe implementar la lógica del estado.
En qué casos aplicar Control Props
Considera usar control props en base a lo siguiente:
- El poder de este patrón es la alta flexibilidad de delegar la lógica del control de estado, por lo que es útil aplicarlo cuando requerimos flexibilidad en la manera en que un componente maneje su estado interno.
Ejemplo de Control Props en vídeo
Si eres más de aprender visualmente o simplemente quieres un resumen rápido, no te pierdas este vídeo donde explico el patrón Control Props en React JS paso a paso:
Ejemplo de Control Props
Para ejemplificar el uso de este patrón vamos a realizar un botón de like en el que cada vez que demos click, tendrá un contador que haga la suma de más uno.
const LikeButton = () => {
const [likes, setLikes] = useState(0)
const handleClick = () => setLikes(likes + 1)
return (
<button onClick={handleClick}>
<span role="img" aria-label="like"></span>
{likes}
</button>
)
}
Como puedes ver, es un componente normal que no tiene nada en especial.
Como en cualquier proyecto, ahora nos piden un nuevo requisito: que el botón de like pueda dar el click sumano más uno y otro botón de like que sume más 5.
¿Cómo lo implementamos?
Una posible manera es pasando un segundo prop que indique la cantidad a sumar y un if preguntando si lo que debe sumar es uno o cinco.
El problema con eso es que cada vez que se requiera agregar más opciones de sumado, nuestro pobre componente va a terminar con una serie de condicionales y complejidad que lo harán difícil de mantener.
Otra posible opción es crear un nuevo componente Button que haga la suma deseada, pero esto es inviable ya que no estamos aprovechando la capacidad de crear componentes reusables.
Otra manera que podría ser viable es refactorizar el componente para que no maneje el estado de los likes, sino que reciba por props, y que sea el componente padre quien decida cuantos likes hay que mostrar. Un ejemplo de esto sería:
const StatelessLikeButton = ({ handleClick, likes }) => {
return (
<button onClick={handleClick}>
<span role="img" aria-label="like"></span>
{likes}
</button>
)
}
Y el componente padre es quien maneja la lógica de cuantos likes sumar.
const ParentStatelessLikeButton = () => {
const [likes, setLikes] = useState(0)
const handleClick = () => setLikes(likes + 5)
return <StatelessLikeButton likes={likes} handleClick={handleClick} />
}
Esto funciona. Dependiendo del contexto donde usemos el botón de like, podemos simplemente pasarle por props la cantidad de likes y el manejador del click para personalizar cuánto sumar.
El problema de esto es la duplicidad de código para el manejo del estado. Imagina que de los N lugares de tu app donde coloques el botón de like, tengas que colocar N veces el estado para el botón.
Puedes decir que se puede crear un custom hook para rehusar la lógica entre los componentes y es verdad, pero lo que estamos haciendo es como "patear el bote" hacia adelante hasta que alguien se haga responsable de manejar la lógica.
Aquí es donde los control props nos pueden ayudar. Vamos a hacer una solución híbrida entre hacer que el botón de like maneje su propio estado interno y dejarlo abierto a que un componente padre maneje su estado.
Con esto aprovechamos lo mejor de dos mundos: tener un estado local pero dejar la opción de delegar el control del estado interno a un componente padre.
const LikeButton = ({ value = null, setValue = null }) => {
const [likes, setLikes] = useState(0)
const isControlled = !!value && !!setValue
const handleClick = () => (isControlled ? setValue() : setLikes(likes + 1))
const getValue = () => (isControlled ? value : likes)
return (
<button onClick={handleClick}>
<span role="img" aria-label="like"></span>
{getValue()}
</button>
)
}
Como puedes ver, estamos manteniendo la lógica de actualización interna pero ahora podemos recibir por props el valor y la función para actualizarlo tal y como lo haríamos con un input de formulario controlado.
Ahora veamos cómo podemos usar este componente de manera sin control y con control para poder ejemplificar su uso en ambas variantes.
Nota que derivado a esto, debemos crear una variable de estado local y su función que la actualice.
export default function App() {
const [value, setValue] = useState(0)
const handleChange = () => setValue(value + 5)
return (
<div className="App">
<h1>Patrón Control Props</h1>
<h2>Sin control</h2>
<LikeButton />
<hr />
<h2>Con control</h2>
<LikeButton value={value} setValue={handleChange} />
</div>
)
}
Con esto ya estamos implementando el patrón de control props. Realmente es muy sencillo aplicarlo y sus beneficios en la flexibilidad hacen que sea una buena alternativa a considerar en tu catálogo de patrones.
Puedes ver y editar el código fuente anterior en este enlace: https://codesandbox.io/s/control-props-u50cr?file=/src/App.js.
Conclusión de Control Props
En este capítulo hemos analizado y comprendido el patrón control props. Te recomiendo que analices bibliotecas open source de terceros donde aplican este patrón para más casos de uso.
Por ejemplo, este componente de Rating de material ui (https://material-ui.com/es/components/rating/)
¿Quieres aprender más sobre patrones de diseño en React JS?
Si te ha gustado este análisis sobre el patrón Control Props, te invito a explorar los otros patrones avanzados en React JS que he analizado en la guía principal.
Y recuerda, si quieres llevar tus habilidades al siguiente nivel, no te pierdas el curso completo en el Canal de YouTube de Developero.