Desestructuración en JavaScript y React-Native
Tags: javascript, reactnative
Published: 2021-09-20 03:56:58

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
```javascript
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
```javascript
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)

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

Otro uso de la coma se complementa con el uso del parámetros rest
```javascript
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

```javascript
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
```javascript
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 (.)

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

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

```javascript
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 

```javascript
let {propiedad1: variable1, propiedad2: variable2} = objeto;
```



```javascript
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"

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

Se puede acceder a una propiedad anidada dentro de un objeto
```javascript
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

```javascript
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

```javascript
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

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


for (let [key, value] of Object.entries(user)) {
  alert(`${key}:${value}`); // name:Kevin, then age:22
}
```


```javascript
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

```javascript
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

```javascript
// 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 

```javascript
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
```javascript
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](https://github.com/paolocarrasco/javascript-style-guide#destructuring)