Componentes Funcionales en Estado vs Estado en React
Spanish (Español) translation by Jean Perez (you can also view the original English article)
React es una popular biblioteca front-end de JavaScript para crear interfaces de usuario interactivas. React tiene una curva de aprendizaje relativamente poco profunda, que es una de las razones por qué está consiguiendo la atención últimamente.
Aunque hay muchos conceptos importantes a cubrir, los componentes son sin lugar a dudas el corazón y el alma de React. Tener una buena comprensión de los componentes debe hacer su vida fácil como desarrollador React.
Requisitos Previos
Este tutorial está destinado a principiantes que han comenzado a aprender a React y necesitan una mejor descripción de los componentes. Vamos comenzar con lo básico del componente y luego pasemos a los conceptos más difíciles como patrones de componente y cuando usar esos patrones. Clasificaciones de los diferentes componentes se han cubierto como clase vs componentes funcionales, stateful vs componentes sin estado y envase vs componentes de presentación.
Antes de comenzar, quiero presentarle el fragmento de código que usaremos en este tutorial. Es un simple contador construido React. Yo se ser refiriéndose a algunas partes de este ejemplo en el tutorial.
Así que vamos a empezar.
¿Cuáles Son los Componentes?
Los componentes son autosostenibles, micro-entidades independientes que describen una parte de la interfaz de usuario. Interfaz de usuario de una aplicación se puede dividir en componentes más pequeños, donde cada componente tiene su propio código, estructura y API.
Facebook, por ejemplo, tiene miles de piezas de funcionalidad entretela juntos al ver su aplicación web. Aquí es un hecho interesante: Facebook consta de 30.000 componentes, y el número está creciendo. La arquitectura de componentes le permite pensar en cada pieza por separado. Cada componente puede actualizar todo su alcance sin estar preocupado por cómo afecta a otros componentes.
Si tomamos del Facebook IU por ejemplo, la barra de búsqueda sería un buen candidato para un componente. Newsfeed de Facebook haría que otro componente (o un componente que alberga muchos subcomponentes). Todos los métodos y trate con la barra de búsqueda de llamadas AJAX sería dentro de ese componente.
Los componentes también son reutilizables. Si usted necesita el mismo componente en varios lugares, eso es fácil. Con la ayuda de sintaxis JSX, puede declarar sus componentes donde desea que aparezcan, y eso es todo.
1 |
<div> |
2 |
Current count: {this.state.count} |
3 |
<hr /> |
4 |
{/* Component reusability in action. */ } |
5 |
<Button sign = "+" count={this.state.count} |
6 |
updateCount = {this.handleCount.bind(this) }/> |
7 |
<Button sign = "-" count={this.state.count} |
8 |
updateCount = {this.handleCount.bind(this) }/> |
9 |
</div> |
Props y State
Componentes necesitan datos para trabajar con. Existen dos maneras diferentes que se pueden combinar componentes y datos: como apoyos o estado. apoyos y el estado determinan qué hace que un componente y cómo se comporta. Vamos a empezar con los apoyos.
Props
Si componentes funciones JavaScript llano, apoyos sería la entrada de la función. Por esa analogía, un componente acepta una entrada (lo que llamamos apoyos), procesa y luego hace algún código JSX.



Aunque los datos de los apoyos están accesibles a un componente, filosofía de reaccionar es que accesorios deben ser inmutable y de arriba hacia abajo. Esto significa que un componente de los padres puede pasar en cualquier datos que quiere a sus hijos como apoyos, pero el componente niño puede modificar sus apoyos. Por lo tanto, si intenta editar los apoyos igual a continuación, recibirá el "no se puede asignar a read-only" TypeError.
1 |
const Button = (props) => { |
2 |
// props are read only
|
3 |
props.count =21; |
4 |
.
|
5 |
.
|
6 |
}
|
State
Estate, por el contrario, es un objeto que es propiedad del componente donde se declara. Su ámbito se limita al componente actual. Un componente puede inicializar su estado y actualizarla cuando sea necesario. El estado del componente padre generalmente termina siendo apoyos del componente infantil. Cuando el estado se pasa fuera del ámbito actual, nos referimos a él como un apoyo.



Ahora que conocemos los conceptos básicos del componente, vamos a echar un vistazo a la clasificación básica de los componentes.
Componentes de Clase vs Componentes Funcionales
Un componente de reacción puede ser de dos tipos: un componente de clase o un componente funcional. La diferencia entre los dos es evidente a partir de sus nombres.
Componentes Funcionales
Los componentes funcionales son sólo funciones de JavaScript. Toman una entrada opcional que, como he mencionado antes, es lo que llamamos objetos.



Algunos desarrolladores prefieren usar las nuevas funciones de flecha ES6 para definir componentes. Funciones de flecha son más compactas y ofrecen una sintaxis concisa para escribir expresiones de función. Mediante una función de la flecha, podemos omitir el uso de dos palabras clave, function y return, y un par de llaves. Con la nueva sintaxis, puede definir un componente en una sola línea como este.
1 |
const Hello = ({ name }) => (<div>Hello, {name}!</div>);
|
Componentes de Clase
Componentes de clase ofrecen más características y con más funciones vienen más equipaje. La razón principal para elegir componentes de clase sobre componentes funcionales es que éstas pueden tener estate.



Hay dos maneras que usted puede crear un componente de clase. La manera tradicional es utilizar React.createClass(). ES6 introdujo un azúcar sintaxis que permite escribir clases que extienden de React.Component. Sin embargo, ambos métodos están diseñados para hacer lo mismo.
Componentes de clase pueden existir sin que el estado también. Aquí es un ejemplo de un componente de clase que acepta una entrada de apoyos y hace JSX.
1 |
class Hello extends React.Component { |
2 |
constructor(props) { |
3 |
super(props); |
4 |
}
|
5 |
|
6 |
render() { |
7 |
return( |
8 |
<div> |
9 |
Hello {props} |
10 |
</div> |
11 |
)
|
12 |
}
|
13 |
}
|
Se define un método constructor que acepta apoyos como entrada. Dentro del constructor, que llamamos super() para pasar por lo que es ser heredado de la clase padre. Aquí hay algunos detalles que usted pudo haber faltado.
En primer lugar, el constructor es opcional mientras se define un componente. En el caso anterior, el componente no tiene un estado, y el constructor no parece hacer nada útil. this.props utilizados en el interior el render() funcionará independientemente de si el constructor está definido o no. Sin embargo, aquí hay algo de la documentación oficial:
Componentes de clase siempre deben llamar al constructor base conprops.
Como práctica recomendada, se recomienda utilizando el constructor de todos los componentes de clase.
En segundo lugar, si estás usando un constructor, usted necesita llamar a super(). Esto no es opcional, y obtendrá el error de sintaxis "llamar a super() perdido en constructor" de lo contrario.
Y mi último punto es sobre el uso de super() vs super(props). Super(props) debe utilizarse si usted va a llamar this.props en el constructor. De lo contrario, utilizar super() sola es suficiente.
Componentes con Estado vs componentes sin Estado
Esta es otra manera popular de clasificar los componentes. Y los criterios para la clasificación es simple: los componentes que tienen el estado y los componentes que no.
Componentes con Estado
Componentes stateful son siempre componentes de clase. Como los componentes anteriormente mencionados, con un estado que obtiene inicializar en el constructor.
1 |
// Here is an excerpt from the counter example
|
2 |
constructor(props) { |
3 |
super(props); |
4 |
this.state = { count: 0 }; |
5 |
}
|
Hemos creado un objeto de estado e inicializado con un conteo de 0. Hay una sintaxis alternativa que se propone hacer este llamar más fácil clase de campos. No es una parte de la especificación de ECMAScript todavía, pero si estás usando un transpiler de Babel, esta sintaxis debe trabajar fuera de la caja.
1 |
class App extends Component { |
2 |
|
3 |
/*
|
4 |
// Not required anymore
|
5 |
constructor() {
|
6 |
super();
|
7 |
this.state = {
|
8 |
count: 1
|
9 |
}
|
10 |
}
|
11 |
*/
|
12 |
|
13 |
state = { count: 1 }; |
14 |
|
15 |
handleCount(value) { |
16 |
this.setState((prevState) => ({count: prevState.count+value})); |
17 |
}
|
18 |
|
19 |
render() { |
20 |
// omitted for brevity
|
21 |
}
|
22 |
|
23 |
}
|
Se puede evitar utilizando el constructor en conjunto con esta nueva sintaxis.
Ahora podemos acceder al estado dentro de los métodos de la clase incluyendo render(). Si vas a usarlos dentro de render() para mostrar el valor de la cuenta corriente, debe colocarlo dentro de llaves como sigue:
1 |
render() { |
2 |
return ( |
3 |
Current count: {this.state.count} |
4 |
)
|
5 |
}
|
La palabra this se refiere a la instancia del componente actual.
Inicializando el estado no es suficiente, necesitamos ser capaces de actualizar el estado con el fin de crear una aplicación interactiva. Si pensabas que esto funcionaría, no, no.
1 |
//Wrong way
|
2 |
|
3 |
handleCount(value) { |
4 |
this.state.count = this.state.count +value; |
5 |
}
|
Reaccionan los componentes cuentan con un método llamado setState para actualizar el estado. setState acepta un objeto que contiene el nuevo estado de la count.
1 |
// This works
|
2 |
|
3 |
handleCount(value) { |
4 |
this.setState({count: this.state.count+ value}); |
5 |
}
|
El setState() acepta un objeto como una entrada, e incremente el valor anterior de la cuenta en 1, que funciona como se espera. Sin embargo, hay un retén. Cuando hay múltiples llamadas setState que lea un valor previo del estado y escriben un nuevo valor en él, nos podríamos terminar con una condición de carrera. Lo significa es que los resultados finales no coinciden con los valores esperados.
Aquí es un ejemplo que debería ser claro para usted. Probar esto en el fragmento de codesandbox arriba.
1 |
// What is the expected output? Try it in the code sandbox.
|
2 |
handleCount(value) { |
3 |
this.setState({count: this.state.count+100}); |
4 |
this.setState({count: this.state.count+value}); |
5 |
this.setState({count: this.state.count-100}); |
6 |
}
|
Queremos setState para incrementar la cuenta por 100, y luego actualizar por 1 y luego que saque 100 que se agregó anteriormente. Si setState realiza la transición de estado en el orden real, obtenemos el comportamiento esperado. Sin embargo, setState es asincrónica, y varias llamadas setState podrían procesar por lotes juntos para una mejor experiencia de interfaz de usuario y rendimiento. Así que el código anterior produce un comportamiento que es diferente de lo que esperamos.
Por lo tanto, en lugar de pasar directamente un objeto, puede pasar en una función de actualización que tiene la firma:
1 |
(prevState, props) => stateChange |
2 |
prevState es una referencia a un estado anterior y está garantizado para estar al día. apoyos se refiere a los apoyos del componente, y no necesitamos apoyos para actualizar el estado, por lo podemos ignorar. Por lo tanto, podemos usarlo para actualizar estado y evitar la condición de carrera.
1 |
// The right way
|
2 |
|
3 |
handleCount(value) { |
4 |
|
5 |
this.setState((prevState) => { |
6 |
count: prevState.count +1 |
7 |
});
|
8 |
}
|
El setState() rerenders el componente, y tiene un componente de estado de trabajo.
Componentes sin Estado
Puede utilizar una función o una clase para crear componentes sin estado. Pero a menos que necesite utilizar un gancho de ciclo de vida de sus componentes, usted debe ir para apátridas componentes funcionales. Hay una gran cantidad de beneficios si usted decide utilizar componentes funcionales apátridos son fáciles de escribir, entender y probar, y se puede evitar la palabra this en conjunto. Sin embargo, a partir de React v16, hay no hay ventajas de rendimiento uso de apátridas componentes funcionales en componentes de clase.
Lo malo es que no tienen ganchos de ciclo de vida. El método de ciclo de vida ShouldComponentUpdate() a menudo se utiliza para optimizar el rendimiento y controlar manualmente qué obtiene generada. Se puede utilizar con componentes funcionales aún. Ref no se admite también.
Componentes del Contenedor vs Componentes Presentación
Este es otro patrón que es muy útil al escribir componentes. La ventaja de este enfoque es que la lógica de comportamiento es separada de la lógica de presentación.
Componentes de Presentación
Presentación componentes están acoplados con la vista o en cómo las cosas se ven. Estos componentes aceptan apoyos de su homólogo de contenedor y hacen. Todo lo que tiene que ver con que describe la interfaz de usuario debe ir aquí.
Presentación componentes son reutilizables y deben permanecer desconectados de la capa de comportamiento. Un componente de presentación recibe los datos y las devoluciones de llamada exclusivamente a través de apoyos y cuando ocurre un evento, como un botón se presiona, realiza una devolución de llamada para el componente de envase a través de apoyos para invocar un método de control de eventos.
Componentes funcionales deben ser su primera opción para escribir componentes de presentación, a menos que un estado es necesario. Si un componente de presentación requiere de un estado, debe preocuparse con el estado de la interfaz de usuario y datos no reales. El componente de presentación no interactuar con el almacén Redux o hacer llamadas a la API.
Componentes del Contenedor
Componentes del Contenedor se ocupará de la parte conductual. Un componente de contenedor indica el componente de presentación lo que se debe representar mediante apoyos. No debe contener estilos y marcas DOM limitadas. Si usas Redux, un componente de contenedor contiene el código que envía una acción a una tienda. Por otra parte, este es el lugar donde debe colocar las llamadas de API y almacena el resultado en el estado del componente.
La estructura generalmente es que hay un componente de contenedor en la parte superior que pasa por los datos a sus componentes de presentación de niño como apoyos. Esto funciona para proyectos pequeños; sin embargo, cuando el proyecto se vuelve más grande y tiene un montón de componentes intermedios que sólo aceptan apoyos y pasarlas a componentes hijos, esto conseguirá desagradable y difícil de mantener. Cuando esto sucede, es mejor crear un componente de contenedor único para el componente de la hoja y esto aliviará la carga sobre los componentes intermedios.
¿Qué es un PureComponent?
Se llega a oír el componente puro término muy a menudo en círculos de reaccionar, y luego hay React.PureComponent. Cuando eres nuevo en reaccionar, todo esto puede sonar un poco confuso. Un componente se dice que es puro si es garantía para devolver el mismo resultado dado los mismos apoyos y estado. Un componente funcional es un buen ejemplo de un componente puro ya que, dada una entrada, sabes lo que se mostrará.
1 |
const HelloWorld = ({name}) => ( |
2 |
<div>{`Hi ${name}`}</div> |
3 |
);
|
Componentes de clase pueden ser puros demasiado mientras sus apoyos y estado son inmutables. Si tienes un componente con un conjunto inmutable 'profundo' de puntales y estado, API de reaccionar tiene algo llamado PureComponent. React.PureComponent es similar a React.Component, pero implementa el método ShouldComponentUpdate() un poco diferente. ShouldComponentUpdate() se invoca antes de que algo es generada. El comportamiento predeterminado es que devuelve true para que cualquier cambio en el estado o los puntales rerenders el componente.
1 |
shouldComponentUpdate(nextProps, nextState) { |
2 |
return true; |
3 |
}
|
Sin embargo, con PureComponent, realiza una comparación superficial de los objetos. Comparación superficial significa que comparar el contenido inmediato de los objetos en lugar de comparar todos los pares de clave y valor del objeto de forma recursiva. Tan sólo las referencias a objetos se comparan y si mutan el estado/apoyos, esto podría no funcionar como se pretende.
React.PureComponent se utiliza para optimizar el rendimiento, y no hay razón por qué usted debe considerar el uso a menos que encuentres a algún tipo de problema de rendimiento.
Reflexiones Finales
Componentes funcionales son más elegantes y generalmente son una buena opción para la construcción de los componentes de presentación. Porque son simplemente funciones, usted no tiene una escritura difícil y entenderlos, y por otra parte, son muerto fáciles de probar.
Cabe señalar que los apátridas componentes funcionales no tienen la mano superior en términos de rendimiento y optimización porque no tienen un gancho ShouldComponentUpdate(). Esto podría cambiar en el futuro versiones de reaccionar, donde componentes funcionales podrían ser optimizados para un mejor rendimiento. Sin embargo, si no eres crítica de la actuación, deben atenerse a componentes funcionales para la vista presentación y componentes stateful de la clase para el contenedor.
Ojala, este tutorial te ha dado una visión de alto nivel de la arquitectura basada en componentes y patrones de diferentes componentes en reaccionar. ¿Cuáles son sus pensamientos sobre esto? Compartirlas a través de los comentarios.
En los últimos años, reacciona ha crecido en popularidad. De hecho, tenemos un número de elementos de Envato mercado que están disponibles para compra, revisión, aplicación y así sucesivamente. Si usted está buscando recursos adicionales alrededor de reaccionar, no dude en comprobar ahora.



