Recentemente, publicamos uma série de artigos sobre o tópico de uso do Couchbase Lite em um aplicativo React Native. Neste tutorial, você dará um passo adiante e usará o Módulo Couchbase Lite para React Native (disponível como um Módulo npm). Você adicionará o código do Couchbase Lite necessário para completar as telas de login e de listagem de um aplicativo Todo simples. Ao final do tutorial, você terá abordado os seguintes conceitos básicos:
- Criação e exclusão de um banco de dados e documentos dentro dele.
- Uso de visualizações do Couchbase para exibir documentos da lista por data.
- Replicações com autenticação básica.
- Criação de usuários do Sync Gateway e uso de uma função de sincronização.
Requisitos
- Node.js 4.0 +
- Xcode 7 ou superior
- Um simulador ou dispositivo iOS com iOS 9 ou superior
Primeiros passos
Para economizar tempo, já criei um projeto inicial que contém todo o código da interface do usuário. Vá em frente e Faça o download no diretório de sua preferência e descompacte o conteúdo. Em seguida, no diretório do projeto, instale as dependências:
|
1 |
$ npm install |
Se ainda não for o caso, certifique-se também de ter a CLI do React Native instalada globalmente:
|
1 |
$ npm install react-native -g |
Em seguida, inicie o daemon do React Native:
|
1 |
$ react-native start |
Abra o projeto do Xcode em ios/UntitledTodoApp.xcodeproj e execute-o no simulador ou no dispositivo a partir do Xcode. Você deverá ver as duas telas:

Observe que o botão Log Out não o leva de volta à tela de log-in e que nada é exibido no ListView. Não se preocupe, isso será corrigido na próxima seção :) Lembre-se de ativar o LiveReload usando a opção Cmd+D (e a depuração do Chrome pode ser útil em alguns momentos).

Persistência local com o Couchbase Lite
O projeto inicial já contém o módulo React Native Couchbase Lite (você pode seguir o guia instruções de repositório para usá-lo em outro projeto React Native). Nesta seção, você aprenderá a instanciar um novo gerenciador, banco de dados e persistir documentos localmente.
Crie um novo arquivo em src/database.js e cole o seguinte:
|
1 2 3 4 5 6 7 8 9 10 11 |
// 1 import {manager, ReactCBLite} from 'react-native-couchbase-lite'; // 2 ReactCBLite.init(5984, 'admin', 'pass'); // 3 var database = new manager('https://admin:pass@localhost:5984/', 'myapp'); // 4 module.exports = database; |
O código faz o seguinte:
- Importar o
gerenteeReactCBLiteobjetos do módulo usando o desestruturação da sintaxe de atribuição no ES6. - Inicie o Listener do Couchbase Lite que serve uma API HTTP REST que você usará posteriormente.
- Instanciar uma instância do gerenciador passando o URL do servidor incorporado e o nome do banco de dados desejado.
- Exporte o objeto para que ele possa ser usado em todo o ciclo de vida do aplicativo.
Agora você pode voltar seu foco para componentes/Login.js. Adicione uma instrução require para usar o objeto de banco de dados da etapa anterior:
|
1 |
var database = require('./../database'); |
Esse componente tem dois campos de entrada e um botão. Por enquanto, você não vai verificar se o usuário existe porque o Sync Gateway ainda não está em funcionamento. No entanto, você precisará inicializar o banco de dados local antes de abrir a visualização de lista. Substitua o corpo de _onLoginButtonPressed com o seguinte:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var remote = `https://${this.state.username}:${this.state.password}@localhost:4984/todos`; var credentials = this.state; database.createDatabase() .then((res) => { database.replicate('myapp', remote, true); database.replicate(remote, 'myapp', true); var todoViews = { lists: { "map": function (doc) { emit(doc.created_at, doc); }.toString() } }; database.createDesignDocument("_design/todo", todoViews); }).catch((err) => { throw err }); var data = {username: credentials.username}; this.props.navigator.push({id: 2, data: data}); |
Aqui, você está criando o banco de dados e, em seguida, registrando um documento de design com uma visualização para consultar documentos por seus created_at propriedade.
Em seguida, abra Listas.js e solicitar o objeto de banco de dados mais uma vez:
|
1 |
var database = require('./../database'); |
No renderizar observe as 2 variáveis leftButtonConfig e rightButtonConfig que são usados no componente NavigationBar na instrução de retorno. Eles correspondem ao Sair do sistema e Novo botões. No entanto, os manipuladores de cliques não fazem nada, portanto, você mudará isso imediatamente. Na seção manipulador campo do literal do objeto leftButtonConfig adicionar:
|
1 2 3 4 5 6 |
database.deleteDatabase() .then((res) => { if (res.ok) { this.props.navigator.pop(); } }); |
Você está simplesmente excluindo o banco de dados (e todos os documentos e possíveis replicações em andamento com ele) e, em seguida, retornando ao LogIn View.
Em seguida, no manipulador para o rightButtonConfig adicionar:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
AlertIOS.alert( 'New List Title', null, [ { text: 'Save', onPress: (text) => { database.createDocument({ type: 'list', title: text, owner: that.props.data.username, created_at: new Date().getTime() }); } }, { text: 'Cancel', style: 'cancel' } ], 'plain-text' ); |
Nesse caso, você está exibindo uma caixa de diálogo de alerta para inserir o novo título da lista e, em seguida, persistindo-o no banco de dados (com a função proprietário definido como o usuário conectado e created_at como o registro de data e hora atual).
Em seguida, abaixo do getInitialState adicione o seguinte para consultar os documentos persistentes:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
_redrawListView: function() { // 1 database.queryView('_design/todo', 'lists') .then((res) => { this.setState({ dataSource: this.state.dataSource.cloneWithRows(res.rows) }); }); }, componentWillMount: function() { // 2 var that = this; that._redrawListView(); this.interval = setInterval(function () { that._redrawListView(); }, 100); }, // 3 componentWillUnmount: function() { clearInterval(this.interval); }, |
Aqui está o detalhamento do que está acontecendo:
_redrawListViewé um método privado que consulta olistase atualiza a fonte de dados para exibir as novas linhas (se houver) na tela.- Em
componentWillMountvocê está usando osetIntervalpara verificar periodicamente se há novos documentos e atualizar a interface do usuário. - Interrompa o método de intervalo quando o componente for desmontado (ou seja, quando retornar à exibição de login).
Crie uma nova lista e abra https://localhost:5984/myapp/_design/todo/_view/lists em seu navegador. Você deve fornecer administrador para o nome de usuário e passe para a senha. A resposta JSON deve ter a seguinte aparência:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
{ "offset":0, "rows":[ { "key":1452038776654, "value":{ "owner":"james", "_id":"-_XbsYkL8LNqVDSMuZceW71", "_rev":"1-e62876578d58bcdef321bb50470debf4", "created_at":1452038776654, "title":"Groceries", "type":"list", "_local_seq":2 }, "id":"-_XbsYkL8LNqVDSMuZceW71" }, ... ], "total_rows":2 } |
Para exibi-los na tela, use o comando Visualização de lista componente. Ele tem dois atributos obrigatórios:
fonte de dadospara fornecer os dados: você pode passarthis.state.dataSource.renderRowusa uma função que retorna umVerdado um item de lista.
Está faltando o método para desenhar a linha, abaixo renderizar, adicione um renderRow com o seguinte:
|
1 2 3 4 5 6 7 8 9 |
renderRow: function(list) { var list = list.value; return ( {list.title} {list.owner} ); } |
Os dados desejados são mantidos no valor e você está exibindo os campos de título e proprietário em Texto elementos. De volta à instrução de retorno do renderizar adicione o método Visualização de lista abaixo do Barra de navegação componente dessa forma:
|
1 2 3 4 |
Persista nos documentos e observe a tela se atualizando:

Configuração do gateway de sincronização
Nesta seção, você usará o Sync Gateway para introduzir a sincronização bidirecional e a autenticação de usuário no lado do servidor para que vários usuários possam fazer login. Primeiro, faça o download do Sync Gateway em aqui e no diretório raiz do projeto, crie um novo arquivo chamado sync-gateway-config.json com o seguinte JSON:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{ "log": ["*"], "databases": { "todos": { "users": { "moderator": {"password": "pass", "admin_channels": ["*"]}, "laura": {"password": "pass"}, "james": {"password": "pass"}, "adam": {"password": "pass"} }, "sync": `function(doc, oldDoc) { var channelname = "chan_" + doc.owner channel(channelname); access(doc.owner, channelname); }` } } } |
Alguns aspectos importantes a serem observados aqui são:
- O
CONVIDADOestá desativado (na verdade, é o caso por padrão), portanto, qualquer solicitação não autenticada será tratada como não autorizada e retornará um código de status 401. Nesse caso, foram criados 4 usuários diferentes (com os nomes moderador, laura, james, adam). O usuário chamado moderador tem acesso a todos os canais. - A função Sync encaminha um documento para um canal com o nome do
proprietárioe concede oproprietárioacesso a esse canal.
Portanto, em teoria, o moderador deve ver todos os documentos da lista, enquanto o outros usuários verão apenas seus próprios documentos da Lista.
Inicie o Sync Gateway na linha de comando:
|
1 |
$ ~/Downloads/couchbase-sync-gateway/bin/sync_gateway ./sync-gateway-config.json |
Em Login.js, atualize o _onLoginButtonPressed como segue:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
// 1 - Request configuration var remote = `https://${this.state.username}:${this.state.password}@localhost:4984/todos`; var credentials = this.state; var settings = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: credentials.username, password: credentials.password }) }; var that = this; // 2 - Check that the name/password are valid fetch(remote + '/_session', settings) .then((res) => { switch (res.status) { case 200: // 3 - Bootstrap application database.createDatabase() .then((res) => { database.replicate('myapp', remote, true); database.replicate(remote, 'myapp', true); var todoViews = { lists: { "map": function (doc) { emit(doc.created_at, doc); }.toString() } }; database.createDesignDocument("_design/todo", todoViews); }).catch((err) => { throw err }); var data = {username: credentials.username}; that.props.navigator.push({id: 2, data: data}); break; case 401: // 4 - Wrong credentials alert('User not found or password incorrect'); break; default: break; } }); |
O que está acontecendo é o seguinte:
- Construa o URL do banco de dados remoto (nesse caso, é um banco de dados do Sync Gateway) e defina os campos JSON de nome/senha no corpo da solicitação.
- Use o POST /_session para verificar o nome/senha com o Sync Gateway.
- Se as credenciais forem válidas, crie o banco de dados e, uma vez feito isso, inicie as replicações push/pull contínuas e registre um documento de design com uma visualização para consultar o documento por seus
created_atpropriedade. - Se as credenciais forem inválidas, exiba uma janela de alerta.
Execute o aplicativo e faça login como usuários diferentes. Se possível, execute o aplicativo em dois dispositivos para observar a replicação contínua e as diferentes permissões de leitura para o moderador:

Conclusão
Neste tutorial, você aprendeu a usar o módulo React Native Couchbase Lite para criar um aplicativo Todo simples em que vários usuários podem fazer login.
O projeto final pode ser encontrado em GitHub.
Sinta-se à vontade para compartilhar seus comentários, descobertas ou fazer perguntas nos comentários abaixo ou nos fóruns. Falamos com você em breve!
Oi James,
parece que esse tutorial já está obsoleto, pois
importar {manager, ReactCBLite} de 'react-native-couchbase-lite'
retorna indefinido para ReactCBLite.
Você poderia atualizar ou indicar algum tutorial real em que as operações de CBL da perspectiva do JS sejam descritas de forma tão clara e abrangente como você fez nesta postagem?