React: Como llenar un Select/Option Padre-Hijo
Tags: react, graphql, select, option
Published: 2020-08-01 03:30:01

<Eng>
How to populate a Select/Option with Father-Children
</Eng>

Llenar un "combobox", el mismo que en HTML se llama "Select" y a sus items, se les denomina "Options" es algo complicado con React. 
En mi base de datos, a manera de reto, utilicé una colección (tabla en SQL) con 2 campos: Nombre de la clase y una lista de las sub clase (una relación padre-hijo, uno a varios), que realmente en Firebase es un campo de tipo Array.
Por ejemplo la clase "TV & Entertaiment", tendría una sub-clase de "Television", "Media Players", "Gaming", "Accesories", etc ...
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/oqfdsdtqk2hj301vltb5.png)

Lo más fácil era realizar un método que reacciones después del clic sobre un Select para que retorne desde la base de datos los valores de la Sub Clase .. sin embargo, cuando utilizas servicios On-Line, como Firebase, te van a cobrar por cada "transacción" que realices, por lo tanto debes ingeniarte en procurar invocar pocas veces a los servicios.
```	
    const QUERY_CLASS = gql`
        query{
            Gear_ClassAll{
                clase_nombre
                sub_clase
            }
        }
    `;
    const { loading, error, data } = useQuery(QUERY_CLASS)
    if (loading) return <p>Loading...</p>
    if (error) return <p>Error :(</p>
    let arrClases = data.Gear_ClassAll
```	

La sentencia de arriba, es una expresión de un ESQUEMA de GraphQL que le permite al cliente obtener los datos.
clase_nombre es un campo de tipo String
sub_clase es un campo de tipo Array.
```
<FormControl as="select"
    value={clase}
    onChange ={(e) => fnLlenarSubClases(e)}>
    <option value="">Select a item ...</option>
    {arrClases.map((item, index) => {
        return <option key={`op${index}`}
            data-tag={item.sub_clase.toString()}
        >{item.clase_nombre}</option>
    })}
</FormControl>
```	

{clase} es una variable de estado, que contiene el nombre y valor del padre. Debido a que el control HTML SELECT permite atributos personalizados donde puedes almacenar cualquier información, vamos a colocar en el atributo data-tag (puede llamarse data-array o data-elementos) el array de sub elementos del padre, o sea los hijos. Para eso convertimos el array, en una cadena con separaciones de ","
```
data-tag={item.sub_clase.toString()}
```	

Ahí radica la magia. Luego cuando el usuario selecciona un elemento del padre, de-construimos la cadena almacenada en el atributo mediante la función .split() y la asignamos a una variable de estado, para que REACT se encargue de construir nuevamente las opciones del Select hijo.
```	
    function fnLlenarSubClases(e) {
        setclase(e.target.value);
        if (e.target.value) {
            setarrSubClases(e.target.options[e.target.selectedIndex].getAttribute("data-tag").split(","))
        } else {
            setarrSubClases([])
        }
        setsub_clase("")
    }
```	

Abajo, la construcción del SELECT hijo.

```	
<FormControl as="select"
    value={sub_clase}
    onChange={(e) => setsub_clase(e.target.value)}>
    <option>Select a item ...</option>
    {arrSubClases.map((item, index) => {
        return <option key={index}>{item}</option>
    })}
</FormControl>
```