SQLite e React Native
Tags: reactnative, database
Published: 2021-02-01 10:30:13

No Tutorial a seguir, será criado um exemplo simples de como criar um app usando React Native e salvando os dados em um banco(SQLite) local. 

Espera-se que voce já tenha seu projeto criado ou crie um novo :) 

Utilizaremos um biblioteca para fazermos uso do SQLite em nosso app. 
Para adicionar o mesmo no projeto, basta inserir o comando abaixo na raiz do seu projeto. 

```sh
yarn add react-native-sqlite-storage
```

# Estrutura de pastas do projeto

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dwhgerbbv6vvf4lw6ume.png)

## Arquivos 

 **schemas.js** 
```js
export const SupportedTypes = {
    INTEGER: {
        value: 'INTEGER',
        type: 'INTEGER',
        default_value: null
    },
    LONG: {
        value: 'LONG',
        type: 'INTEGER',
        default_value: null
    },
    DOUBLE: {
        value: 'DOUBLE',
        type: 'REAL',
        default_value: null
    },
    TEXT: {
        value: 'TEXT',
        type: 'TEXT',
        default_value: null
    },
    BOOLEAN: {
        value: 'BOOLEAN',
        type: 'INTEGER',
        default_value: null
    },
    DATETIME: {
        value: 'DATETIME',
        type: 'TEXT',
        default_value: null
    },
    SYNC_STATUS: {
        value: 'STATUS',
        type: 'TEXT',
        default_value: null
    },
    JSON: {
        value: 'JSON',
        type: 'TEXT',
        default_value: null
    },
};

export const Tables = {
    Movie: {
        name: {
            type: SupportedTypes.TEXT,
            primary_key: false,
            default_value: null,
        },
        description: {
            type: SupportedTypes.TEXT,
            primary_key: false,
            default_value: null,
        },
    },
};
```
**SQLiteManager.js** 

```js
import SQLite from 'react-native-sqlite-storage';

SQLite.DEBUG(true);
SQLite.enablePromise(true);

import * as schema from './schemas';

const database_name = 'Example.db';
const database_version = '1.0';
const database_displayname = 'ExampleDB';
const database_size = 200000;

class SQLiteManager {
    constructor() {
        this.type = 'SingletonDefaultExportInstance';
        this.db = null;
    }

    initDB() {
        let db;
        return new Promise((resolve) => {
            SQLite.echoTest()
                .then(() => {
                    SQLite.openDatabase(
                            database_name,
                            database_version,
                            database_displayname,
                            database_size,
                        )
                        .then((DB) => {
                            this.db = DB;
                            db = DB;
                            db.executeSql('SELECT 1 FROM Movie LIMIT 1')
                                .then(() => {
                                    //
                                })
                                .catch((error) => {
                                    db.transaction((tx) => {
                                            for (const name in schema.Tables) {
                                                this.createTable(tx, schema.Tables[name], name);
                                            }
                                        })
                                        .then(() => {
                                            //
                                        })
                                        .catch(() => {
                                            //
                                        });
                                });
                            resolve(db);
                        })
                        .catch((error) => {
                            //
                        });
                })
                .catch((error) => {
                    //
                });
        });
    }

    closeDatabase(db) {
        if (db) {
            db.close()
                .then((status) => {
                    //
                })
                .catch((error) => {
                    this.errorCB(error);
                });
        } else {
            //
        }
    }

    addMovieReview(movie) {
        return new Promise((resolve) => {
            this.db
                .transaction((tx) => {
                    for (let i = 0; i < movie.length; i++) {
                        tx.executeSql('INSERT OR REPLACE INTO Movie VALUES (?, ?)', [
                            movie[i].name,
                            movie[i].description,
                        ]).then(([tx, results]) => {
                            //
                            resolve(results);
                        });
                    }
                })
                .then((result) => {
                    //
                })
                .catch(() => {
                    //
                });
        });
    }

    createTablesFromSchema() {
        if (this.db) {
            this.db.transaction((tx) => {
                for (const name in schema.Tables) {
                    this.createTable(tx, schema.Tables[name], name);
                }
            });
        }
    }

    dropDatabase() {
        return new Promise((resolve, reject) => {
            SQLite.deleteDatabase(database_name)
                .then(() => {
                    SQLite.openDatabase(
                        database_name,
                        database_version,
                        database_displayname,
                        database_size,
                    );
                })
                .then(() => {
                    resolve();
                })
                .catch((err) => {
                    reject(err);
                });
        }).catch((error) => {
            //
        });
    }

    createTable(tx, table, tableName) {
        let sql = `CREATE TABLE IF NOT EXISTS ${tableName} `;
        const createColumns = [];
        for (const key in table) {
            createColumns.push(
                `${key} ${table[key].type.type} ${
          table[key].primary_key ? 'PRIMARY KEY NOT NULL' : ''
        } default ${table[key].default_value}`,
            );
        }
        sql += `(${createColumns.join(', ')});`;
        tx.executeSql(
            sql,
            [],
            () => {
                //
            },
            () => {
                //
            },
        );
    }
}

export default new SQLiteManager();
```

**MovieRepository.js**

```js
import SQLiteManager from '../SQLiteManager';

export default class MovieRepository {
    addMovieReview(movie) {
        return new Promise((resolve, reject) => {
            SQLiteManager.addMovieReview(movie)
                .then((sqlite) => {
                    resolve(sqlite);
                })
                .catch((error) => {
                    reject(error);
                });
        });
    }
}
```

**MovieController.js**

```js
import MovieRepository from '../database/repository/MovieRepository';

export default class MovieController {
    constructor() {
        this.repository = new MovieRepository();
    }
    addMovieReview(movie) {
        return this.repository.addMovieReview(movie);
    }
}
```

**Main.js**

```js
import React from 'react';
import SQLiteManager from '../../database/SQLiteManager';
import {
    Text,
    StyleSheet,
    TouchableOpacity,
    StatusBar,
    TextInput,
    View,
} from 'react-native';

import MovieController from '../../controller/MovieController';

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    fileName: {
        fontWeight: 'bold',
        marginTop: 5,
    },
    instructions: {
        color: '#000',
        fontSize: 14,
        marginTop: 20,
        textAlign: 'center',
    },
    welcome: {
        marginTop: 40,
        color: '#000',
        fontSize: 22,
        fontWeight: 'bold',
        textAlign: 'center',
    },
    input: {
        margin: 15,
        height: 40,
        borderColor: '#000',
        borderWidth: 1,
    },
    submitButton: {
        backgroundColor: '#000',
        padding: 10,
        margin: 15,
        height: 40,
    },
    submitButtonText: {
        color: 'white',
        textAlign: 'center',
    },
});

class Main extends React.Component {
    constructor(props) {
        super(props);
        this.movieController = new MovieController();
        this.state = {
            name: '',
            description: ''
        };
    }

    componentDidMount() {
        SQLiteManager.initDB();
    }

    handleName = (text) => {
        this.setState({
            name: text
        });
    };
    handleDescription = (text) => {
        this.setState({
            description: text
        });
    };
    save = (name, description) => {
        const data = {
            name,
            description
        };
        const arrData = [];
        arrData.push(data);
        this.movieController
            .addMovieReview(arrData)
            .then(() => {
                alert('Reseha salva :)');
                this.setState({
                    name: '',
                    description: ''
                });
            })
            .catch(() => {
                alert('Error ao salvar resenha :(');
            });
    };

    render() {
        return ( <
                View style = {
                    styles.container
                } >
                <
                StatusBar barStyle = "light-content"
                backgroundColor = "#000" / >
                <
                Text style = {
                    styles.welcome
                } > SQLite e React Native < /Text> <
                Text style = {
                    styles.instructions
                } >
                Insira sua resenha sobre um filme = ) <
            /Text> <
            TextInput
        style = {
            styles.input
        }
        underlineColorAndroid = "transparent"
        placeholder = "Nome do Filme"
        placeholderTextColor = "#000"
        autoCapitalize = "none"
        value = {
            this.state.name
        }
        onChangeText = {
            this.handleName
        }
        />

        <
        TextInput
        style = {
            styles.input
        }
        underlineColorAndroid = "transparent"
        placeholder = "Descricao"
        placeholderTextColor = "#000"
        autoCapitalize = "none"
        value = {
            this.state.description
        }
        onChangeText = {
            this.handleDescription
        }
        /> <
        TouchableOpacity
        style = {
            styles.submitButton
        }
        onPress = {
                () => this.save(this.state.name, this.state.description)
            } >
            <
            Text style = {
                styles.submitButtonText
            } > Salvar < /Text> <
            /TouchableOpacity> <
            /View>
    );
}
}

export default Main;
```



## Screens

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/19u5rz83bywsnnr9u8f1.jpeg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/j9awzfv0y80cscb44ojh.jpeg)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2vnolp692kkkuaz0a7w5.png)

## Até a próxima :)

Um tutorial bem direto ao ponto. Tem possibilidade para melhorar o código, mas para algo rápido e direto, está bem claro. Dúvidas, críticas ou sugestões...basta comentar :p

Link do projeto: https://github.com/mensonones/RNSQLite