How JS Symbols helps frontEnd developer to keep Metadata: 
Tags: javascript, symbol, frontend, typescript
Published: 2020-06-28 11:11:19

As a frontend Developer maybe you ask yourself what is the advantages of using **Symbols**? How it could help us to have cleaner and better code? 
In this article we do not go in deep of the  symbols specification, we try to use symbols In real app and see how it helps frontend world. if you search in google you will find  a lot of resources about the [symbols specification](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol). 

One of the common question which my friends always ask me on frontend developing is how to keep metadata related to the object which fetched fron the backend or rest api such as isLoading, is Edited, ... . 

Imagin we want to show a book in a list with pagination from backend
```json
    {
        "title":"Javascript",
        "author":{
            "name": "Aliakbar",
            "family":"Salehi"
        },
        "tags": ["javascript", "React", "frontend", "web"]
    }
```
 and let user to select, edit or delete it.
In this situation we need metadata to keep the status of the book object
* what is the index of the current book
* is book data changed?
* what is the current view of the book (edit, read, new, loding)
* Errors on communication with data (update Error, delete error, ... )

theere are several data structure to keep these metadata:
1. keep metadata seperated and connect to origin object via Identifier key:
    ```javascript 
        const book={
            "title":"Javascript",
            "author":{
                "name": "Aliakbar",
                "family":"Salehi"
            },
            "tags": ["javascript", "React", "frontend", "web"],
        }

        const metaData={
            isLoading:false,
            edited: false,
            mode: viewMode.Read
            index:12,
            totoalBooks: 128,
        }
    ```
2. add metadata inside the original Object 
    ```javascript
        const book={
            "title":"Javascript",
            "author":{
                "name": "Aliakbar",
                "family":"Salehi"
            },
            "tags": ["javascript", "React", "frontend", "web"],
            __metadata:{
                isLoading:false,
                edited: false,
                mode: viewMode.Read
                index:12,
                totoalBooks: 128,
            }
            
        }
    ```

by default second approach is easier to read and access metadata specially when we work with a list of items, but it needs to sanitize the data and remove `__metadata` before sending the change into the backend as it is just client side metadata. 

### The magic of  **Symbol Properties**:
I use always metadata inside the origin object as a Symbol property,
```javascript
        const book={
            "title":"Javascript",
            "author":{
                "name": "Aliakbar",
                "family":"Salehi"
            },
            "tags": ["javascript", "React", "frontend", "web"],
            [Symbol.for("metadata")]:{
                isLoading:false,
                edited: false,
                viewMode: viewMode.Read
                index:12,
                totoalBooks: 128,
            }
        }
```
this approach has several advantage: 

* As you know, Symbol properties in Object acts as a private hidden property, so you can use `JSON.stringify(book)` without any concern about the metadata. [read more](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Symbols%20and%20JSON.stringify())
    ```javascript
        /// update book after change
        restApi.Update(JSON.stringify(book))
        /// metadata property will be sanitized automatically without any effort or extra code
    ```

* abother benifit of metadata as a symbol property is Symbols are not `enumerable` in `for...in` iterations.
so you can  iterate without any concern or extra logic/code in items ( it is to helpful when you use some libraries such as [**`normalizr`**](https://github.com/paularmstrong/normalizr) to normalize yorur data)


* easy to access the metadata or change them 
    ```javascript
        book[Symbol.for("metadata")].isLoading = true;
        // or 
        const {mode , isLoading}= book[Symbol.for("metadata")]
        if(isLoading)
            renderBook( mode)
        else 
            renderLodingComponent()
    ```


<hr/>


[Aliakbar Salehi](https://salehi186.github.io/)