Desarrollando aplicaciones con ReactJS

0
1427

Índice de Contenidos

  1. Introducción
  2. NPM y Yarn
  3. ECMAScript y Babel
  4. Uso de Composición en lugar de Herencia
  5. Uso de React Hooks
  6. Conclusiones
  7. Referencias

1. Introducción

A día de hoy hay muchas aplicaciones que funcionan con éste framework. Ya hemos hablado de ReactJS en más de una ocasión y sabemos las ventajas que nos proporciona utilizarlo para desarrollar el frontal de nuestra proyecto.

Por eso me gustaría en este artículo apuntar conceptos necesarios y utilidades de React útiles de cara a aprovechar todo su potencial en un proyecto real.

2. NPM y Yarn

Sabemos que para poder trabajar con ReactJS necesitamos tener instalado en nuestro entorno local NodeJS, que a su vez nos instala npm para manejar los paquetes de otras librerías y así poder usarlas. Todas las librerías que van a conformar nuestro proyecto están descritas en el fichero package.json. Si ejecutamos el comando:

npm install

npm instalará los paquetes incluidos en el fichero.

Una alternativa a npm es Yarn. Fue lanzado en 2016 por Facebook en colaboración con Exponent, Google y Tilde y tiene como objetivo manejar las dependencias de manera fiable. La sintaxis es muy similar a npm y solo basta escribir en consola:

yarn

para instalar todas las dependencias listadas en el mismo fichero package.json.

Yarn es utilizado en producción por Facebook y se incluye en proyectos como React, React Native y Create React App. Además, incluye un fichero adicional yarn.lock con el objetivo de tener consistencia entre las distintas máquinas sobre las que pueden estar desplegadas las dependencias de tal manera que en ese fichero se registra exactamente la versión de cada dependencia instalada. Un ejemplo de este fichero:

3. ECMAScript y Babel

La evolución de JavaScript ha sido guiada por un conjunto de diferentes compañías y miembros. El comité que se ha encargado de la guía y el avance de las distintas reglas del lenguaje durante los años ha sido la European Computer Manufacturers Association (ECMA) lanzando el conjunto de especificaciones de ECMAScript, al que se ajusta JavaScript. Cuando una nueva versión de ECMAScript es lanzada los distintos navegadores tienen que ir cambiando y ajustándose a dichos cambios para que puedan ser soportados.

Babel es una herramienta para la compilación de Javascript de manera que se encarga de convertir el código a versiones compatibles del mismo antes de ejecutarlo si el navegador utilizado no soporta versiones tan recientes. No es un proceso de compilación tan tradicional como el de otros lenguajes, el código JavaScript no se compila a binario; sino que en su lugar se transforma en una sintaxis más ampliamente aceptada por navegadores.

Un ejemplo sería si la array function del siguiente método map de javascript no fuese compatible con el navegador, se transformaría de la siguiente manera:

// Babel Input: ES2015 arrow function
[1, 2, 3].map((n) => n + 1);

// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {
  return n + 1;
});

4. Uso de Composición en lugar de Herencia

Existen dos maneras de crear componentes en React: con clases y con funciones. Poniendo un sencillo ejemplo:

Función

const Person = (props) => {
  return (
    <div>
      <h1>Hello, {props.name}</h1>
    </div>
  )
}
export default Person;

Clase

class Person extends Component {
 constructor(props){
 super(props);
   this.state = { name: '' };
 }
 
 render() {
   return (
     <div>
       <h1>Hello {this.state.name}</h1>
     </div>
   );
 }
}
export default Person;

Ambas maneras son perfectamente correctas para la implementación, pero React está comenzando a alejarse del uso de clases. Algunas razones de esto son porque los componentes funcionales son más fáciles de leer y testear.

Por otra parte, React promueve no usar jerarquía de herencias ya sea implementando componentes como clases o como funciones ya que tiene un potente modelo de composición para ello que permite fácilmente personalizar el aspecto y comportamiento de un componente mediante el uso de props.

Poniendo como ejemplo el fragmento de código de ejemplo de la documentación de React, esta personalización la podemos hacer de la siguiente manera:

const SplitPane = (props) => {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  )
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}

De manera que al componente de SplitPanel podemos pasar cualquier elemento y renderizarlo correctamente en su lógica, así como reutilizarlo las veces que nos haga falta y con diferentes configuraciones.

5. Uso de React hooks

Se ha comentado en tutoriales anteriores acerca de esta característica de la versión 16.8 de React en adelante. Los hooks nos permiten usar el estado y otras característica de React sin escribir una clase.

Aparte de los hooks básicos y de gran utilidad como son useState, useEffect y useContext existen otros que no son tan utilizados pero a veces nos pueden llegar ser muy útiles:

useCallback y useMemo

En la documentación oficial de React dice que useCallback devuelve un callback memorizado y useMemo devuelve un valor memorizado. Pero ¿qué significa exactamente esto? Pues que useCallBack devuelve una función sin llamar para que pueda llamarse después y useMemo ya llama a la función y además devuelve su valor tras ejecutarse. Vamos a ver un ejemplo con el siguiente código:

export const App = () => {
  const hello = () => {
    return "Hello world";
  };

  const memoizedCallback = useCallback(hello, []);
  const memoizedResult = useMemo(hello, []);

  const results = () => {
    console.log(memoizedCallback);
    console.log(memoizedResult);
    console.log(memoizedCallback());
    console.log(memoizedResult());
  };

  return (
    <div>
      <div>
        <button onClick={results}>Button</button>
      </div>
    </div>
  );
};

Lo que nos devolvería tras pulsar el botón:

console.log(memoizedCallback);
// ƒ hello() {
//   return 'Hello world';
// }
console.log(memoizedResult); // 'Hello world'
console.log(memoizedCallback()); // 'Hello world'
console.log(memoizedResult()); // TypeError

La llamada al valor de la función con useCallBack nos devuelve la función evitando así ejecutar la función, mientras que si ejecutamos la llamada nos devuelve el valor de ‘Hello world’. Con useMemo nos basta con una única llamada a su valor ya que previamente se ha ejecutado la función y el valor se ha cacheado. Además, si se intenta llamar a la ejecución de la llamada de useMemo esto nos devolvería un TypeError.

¿Cuándo usar uno u otro entonces? useMemo es útil cuando queremos ejecutar algo costoso y tenerlo almacenado de primeras en nuestra caché para operar con ello. useCallBack nos permite un mayor control sobre las ejecuciones de las funciones, y es útil cuando éstas se tienen que ejecutar más de una vez.

useRef

En React, un ref es un objeto que almacena valores durante el ciclo de vida de un componente. Esto nos puede ser útil si queremos acceder a algunos elementos del DOM de nuestra aplicación (como campos de un formulario) directamente.

React nos proporciona el hook useRef para poder hacer uso de esta característica y que podamos crear y gestionar nuestro ref.

Podemos ver esto con un ejemplo:

export const AddColorForm = () {
  const titleInput = useRef()
  const colorInput = useRef()

  const submit = e => { 
    e.preventDefault();
    const title = titleInput.current.value 
    const color = colorInput.current.value
    // Hacer llamada POST con title y color
    titleInput.current.value = "" 
    colorInput.current.value = ""
  }

  return (
    <form onSubmit={submit}>
      <input ref={titleInput} type="text" placeholder="color title..." required />
      <input ref={colorInput} type="color" required />
      <button>ADD</button>
    </form>
  )
}

De esta manera estamos dándole valor a los inputs del formulario, dándole una referencia a los campos de los inputs a las variables titleInputcolorInput gracias a useRef y así poder tener acceso a ellos e incluso resetear los valores mediando la propiedad .current cuando hacemos submit. La función e.preventDefault() se utiliza para prevenir que el navegador haga una llamada POST a la URL actual en la que está el formulario con sus valores almacenados en el DOM; pues nosotros queremos realizar la llamada POST con los valores que gestionamos con nuestra ref.

Sin embargo, existe una manera mejor de hacer esto en lugar de usar refs. Podemos hacerlo de manera que sea una programación menos imperativa y no tengamos que acceder directamente a los elementos del DOM. Se puede implementar lo que se llama un componente controlado lo que significa que es React quien se encarga de controlar completamente su estado para que sea un código más robusto y las validaciones de los campos puedan hacerse con gran facilidad.

En lugar usar refs vamos a guardar los valores de titlecolor usando useState y además los usaremos directamente en el value del input. El evento onChange se encargará de modificar el estado de los datos:

export const AddColorForm = () { 
  const [title, setTitle] = useState("");
  const [color, setColor] = useState("#000000");
  
  const submit = e => { 
    e.preventDefault(); 
    // Hacer llamada POST con title y color
    setTitle("");
    setColor("");
  };
  
  return (
    <form onSubmit={submit}>
      <input
        value={title}
        onChange={event => setTitle(event.target.value)}
        type="text"
        placeholder="color title..."
        required
      /> 
      <input
        value={color}
        onChange={event => setColor(event.target.value)}
        type="color"
        required
      />
    <button>ADD</button>
  </form>  
  );
}

De esta sencilla forma, React es quien se encarga de controlar el estado de los datos manejados por el formulario. Cabría destacar que este tipo de implementaciones de componentes están continuamente renderizando el componente (cada vez que se pulse una tecla por el evento onChange). React está diseñado para manejar esta carga de trabajo sobre la rerenderización del componente, pero habría que tenerlo en cuenta para no añadir procesos que sean costosos a cada nueva renderización o hacer implementaciones diferentes como quitar el onChange del input y añadir onclick sobre el botón para que haga lo mismo y únicamente se guarde el estado de los datos una única vez.

useReducer

Este hook tiene como concepto el método reduce de JavaScript. Básicamente coge el estado actual y devuelve un nuevo estado. Esto es útil para el manejo de eventos o si queremos alternar en un estado a otro de un elemento (como un checkbox).

Viéndolo con un ejemplo de un contador con dos estados o acciones:

const initialState = {count: 0};

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

const Counter = () {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

Inicialmente state tiene como valor initialState (count:0). Si hacemos click para decrementar o incrementar valor, el hook useReducer nos cambia de estado sin necesidad de implementar funciones adicionales para setear el valor de cada uno de los estados. De esta forma, eliminamos la necesitad de utilizar useState y mejoramos el rendimiento.

6. Conclusiones

ReactJS es un framework que ha avanzado mucho para intentar adaptarse a la necesidad de las funcionalidades de las aplicaciones web actuales. Ha cambiado mucho desde las primeras versiones, por tanto es importante actualizarse y utilizar todo el potencial actual de cara desarrollar un código útil y eficiente.

7. Referencias

 

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad