Class Components ⚛️
- Autor
- Name
- Anibal Santos
- Publicado
- Lectura
- 4 '
En esta entrada vamos a hablar sobre los componentes de clase en React, diferencias con los componentes función y ciclos de vida del componente.
Actualmente se trabaja más con functional components, pero los class components siguen siendo utilizables y en algunos casos pueden resultar más fáciles de usar.
Ejemplo de componente clase:
class Welcome exntends React.Component { render() { return <h1>Hello {this.props.name}</h1> }}<Welcome name="Anibal"/>
Diferencias entre tipos de componentes:
Function based components
- Reciben props
- Devuelven
JSX
- Las propiedades son de solo lectura
- La performance es mejor que en los componentes de clase
Class based components
- No reciben nada, extienden de React.Component
- Tienen un método
render
que devuelveJSX
- Accedemos a las propiedades mediante
this
:this.props.name
- Tenemos disponible un estado interno de componente.
- Podemos inicializar el estado en el
constructor
- Tenemos ciclos de vida como en otros frameworks como Vue o Angular
¿Cuándo deberíamos utilizar cada tipo de componente?
Actualmente con la llegada de los Hooks, podemos hacer la mayoría de componentes como funciones o como clases. La elección va a depender de diferentes factores como:
- Performance.
- Mantenimiento.
- Facilidad en el desarrollo.
Normalmente si la situación es indiferente se suele utilizar componentes como función. Un ejemplo real de componente clase sería el siguiente:
import React from 'react'import TodoList from './components/TodoList'import TodoForm from './components/TodoForm'class App extends React.Component { constructor(props) { super(props) this.addItem = this.addItem.bind(this) this.removeItem = this.removeItem.bind(this) this.markTodoDone = this.markTodoDone.bind(this) this.state = { todos: [ { value: 'Ordenar la casa', done: true }, { value: 'Hacer ejercicio', done: false }, ], } } addItem(todoItem) { const newTodo = { index: this.state.todos.length + 1, value: todoItem, done: false, } this.setState({ todos: [...this.state.todos, newTodo] }) } removeItem(itemIndex) { this.setState((prevState) => ({ todos: prevState.todos.filter((item, idx) => idx !== itemIndex), })) } markTodoDone(itemIndex) { const todos = [...this.state.todos] todos[itemIndex] = { ...todos[itemIndex], done: !todos[itemIndex].done } this.setState({ todos }) } render() { return ( <div id="main" className="App"> <h1>Todo List</h1> <TodoList items={this.state.todos} removeItem={this.removeItem} markTodoDone={this.markTodoDone} /> <TodoForm addItem={this.addItem} /> </div> ) }}
Respecto al estado de los componentes nos sucede como en los componentes función; no podemos modificarlo directamente, deberemos utilizar el método setState
para modificar nuestro estado del componente.
Ciclos de vida en los componentes de clase:
Mounting: cuando se crea el componete y se renderiza.
Las fases son:
- Se ejecuta el
constructor
. - Se ejecuta el método
render
. - React actualiza el DOM y refs.
- Se ejecuta el método
componentDidMount
Una vez montado, el constructor nunca se vuelve a llamar.
Updating: cuando algo hace que se actualice el componente y se vuelve a renderizar. Por ejemplo el padre del componente modifica las propiedades y el componente hijo vuelve a renderizarse.
Las fases son:
- Se ejecuta el método
render
(se da cuando tenemos nuevas propiedades,setState()
, oforceUpdate()
). - React actualiza el DOM y refs.
- Se ejecuta el método
componentDidUpdate
Las modificaciones de las propiedades o el estado hacen que el componente se actualice, pero no se desmonta y vuelve a montarse. Lo que sucede es que se vuelve a llamar al método render
.
Unmounting: cuando se desmota el componente y desaparece. Por ejemplo cuando en una navegación pasamos de una pantalla a otra y el componente ya no aplica en la nueva pantalla.
Solo tenemos una única fase:
- Se ejecuta el método
componentWillUnmount
En este caso el método se ejecuta justo antes de que se desmonte.
Métodos del ciclo de vida:
componentDidMount
:
- Se ejecuta cuando se ha producido la primera renderización del componente.
- Nos sirve para añadir información al DOM. Operar con el DOM, porque hasta que no lo tenemos disponible no podemos manipularlo.
- Inicializar timers.
- Setear suscripciones.
- Cargas de datos. Por ejemplo el consumo de una api para cargar datos.
Siempre que utilicemos timers o suscripciones, deberemos ejecutar el método componentWillUnmount
para cancelar los timers o las suscripciones. Si no los matamos tendremos una fuga de memoria.
componentDidUpdate
:
- Este método se ejecuta inmediatamente después de que suceda la actualización de o bien props o el estado.
- Cargas de datos. Por ejemplo en una vista de detalle, el id de los elementos va cambiando, entonces actualizamos la información de ese componente.
- Llamar al método
setState
, para setear el estado comparando el estado anterior y el estado actual.
componentWillUnmount
:
- Es invocado inmediatamente antes de desmontar y destruir el componente.
- Limpiar el componente.
- Cancelar peticiones.
- Cancelar timers
- Eliminar suscripciones.
Ejemplo:
import React from 'react'class Header extends React.Component { componentDidMount() { window.alert('mount') } componentDidUpdate() { window.alert('update') } render() { return ( <header onClick={this.props.onClick}> <h1>{this.props.title}</h1> <nav> <ul> <li>Option 1</li> <li>Option 2</li> <li>Option 3</li> <li>Option 4</li> </ul> </nav> </header> ) }}
const App = () => { const [title, setTitle] = useState('React Training') const handleHeaderClick = () => { setTitle(`${title} Classes`) } return ( <div> <Header title={title} handleClick={handleHeaderClick} />; </div> )}
❤️ Espero que te haya gustado la entrada.
Puedes continuar leyendo el siguiente capítulo sobre Hooks, volver al capítulo anterior de Functional components, o volver al Índice.