Desestructuración en JavaScript y React-Native

Desestructuración en JavaScript y React-Native

La palabra desestructuración proviene del verbo desestructurar y se define algo así como quitar una estructura definida y en su uso en el lenguaje javascript es más o menos eso, pero se puede decir que es extraer una propiedad de un objeto aunque también se usa en arreglos, en general en programación siempre manipulamos con estructuras de datos y esta característica ayuda muchísimo.

Esta característica fue introducida en ES6 y su uso en JavaScript en la actualidad es amplio está por todos lados en frameworks como React, Angular, Vue y en casi cualquier proyecto desde el más pequeño al más grande te podrás encontrar con esta práctica.

Ejemplos en arreglos

Tradicionalmente para acceder a los elementos de un arreglo se usa la posición la que se encuentran

let frutas = ['banana', 'manzana', 'pera'];
let banana = frutas[0];
let manzana = frutas[1];
let pera = frutas[2];

Claro esto funciona pero es una sintaxis demasiado larga y la podemos simplificar de la siguiente forma

let frutas = ['banana', 'manzana', 'pera'];
let [banana, manzana, pera] = frutas; 

console.log(banana, manzana, pera); // Resultado: 'banana', 'manzana', 'pera'

De esta forma accedemos de forma implícita a los elementos del arreglo y asignamos directamente sus elementos a las variables que deseamos. Podemos incluso saltar algunos elementos usando la , (coma)

let frutas = ['banana', 'manzana', 'pera'];
let [banana,,] = frutas;

Otro uso de la coma se complementa con el uso del parámetros rest

let frutas = ['banana', 'manzana', 'pera'];
let [banana,..rest] = frutas; 
console.log(rest) // Resultado ['manzana', 'pera']

También se puede combinar su uso con funciones como split, imaginemos que tenemos que separar un nombre que viene en un solo string

let [nombre, apellido] = "Kevin Gracia".split(' ');
console.log(nombre); // Kevin
console.log(apellido);  // Gracia

Ejemplos en objetos

Los objetos en javascript son estructuras de lo más común en Javascript y siempre se trata con ellos ya que son devueltos como respuesta desde algún servicio como una API o una Base de Datos

Suponiendo que tenemos un objeto persona

let persona  = {
firstname: "Kevin",
lastname: "Gracia"

Antes de ES6 para acceder al objeto y asignar su valor en variables se usaba la notación de punto (.)

let firstname = persona.firstname;
let lastname: persona.lastname;

Nuevamente se puede simplificar esta asignación con la desestructuración de la siguiente forma

let {firstname, lastname} = persona;

Y listo ya podemos usar las variables con los valores de las propiedades dentro del objeto persona

También podemos realizar una reasignación de la propiedad en una variable es una práctica muy común

Su sintaxis sería la siguiente

let {propiedad1: variable1, propiedad2: variable2} = objeto;
let {firstname: fname, lastname: lname} = persona;

Un error común es tratar de acceder a una propiedad que no existe por lo cual dará como respuesta "undefined"

let {firstname, midname, lastname} = persona;
console.log(midname) // Respuesta undefined

Se puede acceder a una propiedad anidada dentro de un objeto

const user = { 
        'name': 'Kevin',
        'address': 'Parada 12',
        'age': 22,
        'department':{
            'name': 'Develop',
            'Shift': 'Morning',
            'address': {
                'city': 'Quito',
                'street': '12th October',
                'zip': 1234
            }
        }
}

const { department: { address } } = user;

Ejemplos en funciones al recibir como parámetro

En lugar de recibir el objeto completo y luego desestructurar dentro de la función podemos recibir la propiedad lista para su uso

const cars = [
  { model: 'Camaro' },
  { model: 'Cayenne' }
];

const models = cars.map(
  function({ model }) {
    return model;
  }
);

models; // => ['Camaro', 'Cayenne']

Otro uso posible es dentro del bucle for ... of donde podemos iterar en las propiedades del objeto

const heroes = [
  { name: 'Batman' },
  { name: 'Joker' }
];

for (const { name } of heroes) {
  console.log(name); // Respuesta 'Batman', 'Joker'
}

Y con método Object.entires para obtener las clave 7 valores del objeto

let user = {
  name: "Kevin",
  age: 2
};


for (let [key, value] of Object.entries(user)) {
  alert(`${key}:${value}`); // name:Kevin, then age:22
}
function calculateArea({ width, height }) {
  console.log('Area is ' + width * height);
}

calculateArea({ width: 5, height: 6 }); 
// -> Area is 30

Ejemplo de uso en React Native donde se extrae el año de la ventana del dispositivo y y se la asigna a una nueva variable para después ser usada

const {width: windowWidth} = Dimensions.get('window');

Incluso esta técnica es recomendada en la guía de estilos de airbnb de javascript de la siguiente forma donde tomo el mismo ejemplo

// mal
function processInput(input) {
  // then a miracle occurs
  return [left, right, top, bottom];
}

// el que llama necesita pensar en el orden de la data de retorno
const [left, __, top] = processInput(input);

// bien
function processInput(input) {
  // then a miracle occurs
  return { left, right, top, bottom };
}

// el que llama elige solo la data que necesita
const { left, top } = processInput(input);

¿Por qué? Puedes agregar nuevas propiedades en el tiempo o cambiar el orden de las cosas sin afectar la forma en que se llama.

Para concluir esta guía un ejemplo de React Native donde se usa la técnica de múltiples formas

import React from 'react';
import {ActivityIndicator, Dimensions, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Carousel from 'react-native-snap-carousel';
import {MoviePoster} from '../components/MoviePoster';
import {useMovies} from '../hooks/useMovies';

export const HomeScreen = () => {
  const {peliculasEnCine, isLoading} = useMovies(); // trae las variables de los hooks internos del hook use Movies
  const {top} = useSafeAreaInsets();

  const {width: windowWidth} = Dimensions.get('window'); //desestructuracion y renombrarlo

  if (isLoading) {
    return (
      <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
        <ActivityIndicator color="red" size={100} />
      </View>
    );
  }

  return (
    <View style={{marginTop: top + 20}}>
      <View style={{height: 440}}>
        <Carousel
          data={peliculasEnCine}
          renderItem={({item}: any) => <MoviePoster movie={item} />}
          sliderWidth={windowWidth}
          itemWidth={300}
        />
      </View>
    </View>
  );
};

En este caso el Hook personalizado "useMovies" retorna un objeto con dos propiedades como lo indica la buena práctica mencionada anteriormente

import {useEffect, useState} from 'react';
import movieDB from '../api/movieDB';
import {Movie, MovieDBNowPlaying} from '../interfaces/movieInterface';

export const useMovies = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [peliculasEnCine, setPeliculasEnCine] = useState<Movie[]>([]);

  const getMovies = async () => {
    const resp = await movieDB.get<MovieDBNowPlaying>('/now_playing');
    const peliculas = resp.data.results;
    setPeliculasEnCine(peliculas);

    setIsLoading(false);
  };

  useEffect(() => {
    //now_playing
    getMovies();
  }, []);

  return {
    peliculasEnCine,
    isLoading,
  };
};

Como hemos visto a lo largo de este post la desestructuración es una propiedad muy usada y que se debe tener muy en cuenta al usar React

Referencias Guía de estilos Javascript Airbnb