Advertisement
  1. Code
  2. JavaScript
  3. React

Persistenza dei Dati e Sessioni in React

Scroll to top
Read Time: 9 min
This post is part of a series called Getting Starting with React.
Getting Started With React
Using JSX and React

() translation by (you can also view the original English article)

filefilefile

Avere a disposizione una funzione "remember me" è davvero molto utile, e l'implementazione con React e Express è relativamente facile. Continuando dall'ultima parte dove abbiamo impostato un'applicazione chat WebRTC, aggiungeremo ora sessioni persistenti con Mongo e un database di un elenco online di utenti.

Sessioni?

Se non avete mai usato sessioni finora, in breve sono molto simili ai cookies, nel senso che le sessioni vi consentono di tracciare gli utenti attivi dell'applicazione in tempo reale. Le sessioni lavorano attraverso un session cookie che viene inoltrato nell'header  request / response dall'applicazione.

Così cookies e sessioni sono intrecciate per natura. Quindi perché necessitiamo delle sessioni se abbiamo già i cookies? Ciò che vi danno in aggiunta le sessioni è l'abilità di definire il back-end usato dalla vostra applicazione. Significa che ogni volta che l'informazione viene richiesta dalla vostra applicazione può essere richiamata dal database.

Così in un esempio di vita reale per la nostra chat, ora possiamo memorizzare l'username dell'utente — e se abbiamo riconfigurato un po' l'applicazione, possiamo anche inserire l'intera cronologia della chat nel database per la registrazione.

In questo prossimo esempio useremo un database Mongo per l'archiviazione persistente lato back-end. Questa è una delle diverse opzioni per l'archiviazione della sessione, e memcache è un'altra che raccomandiamo altamente per la configurazione in produzione in larga scala .

Archiviazione dei documenti

Mongo è un motore di archiviazione di documenti NoSQL piuttosto che un archivio di dati relazionale come il popolare MySQL. È davvero facile prendere confidenza con NoSQL se provenite da MySQL o databases simili e avete bisogno di avvicinarvi velocemente a Mongo — non vi ci vorrà molto. Le differenze più importanti che dovreste conoscere sono le seguenti:

  • Come suggerisce il nome, NoSQL non utilizza SQL per eseguire queries. Invece i dati vengono estratti con chiamate al metodo; ad esempio db.collectionName.find() sarebbe SELECT * FROM table.
  • La terminologia è differente: in MySQL abbiamo Tabelle, Righe e Colonne, mentre in Mongo sono presenti Collezioni, Documenti e Chiavi.
  • I dati sono strutturati nello stesso modo in cui è strutturato un oggetto JSON.

Se non avete ancora Mongo, installatelo attraverso il vostro package manager. Nelle distribuzioni Linux per esempio:

1
$ sudo apt-get install mongodb

Una volta installato Mongo possiamo semplicemente aggiungere il supporto di Mongo alla nostra applicazione con il modulo mongoose disponibile attraverso npm. Installate mongoose nel modo seguente:

1
$ npm install mongoose --save

Aggiungiamo ora Mongo alla nostra applicazione. Aprite il vostro editor, aprite app.js e impostate la parte alta del vostro script nel modo seguente.

1
//Configure our Services
2
var PeerServer = require('peer').PeerServer,
3
    express = require('express'),
4
    mongoose = require('mongoose'),
5
    assert = require('assert'),
6
    events = require('./src/events.js'),
7
    app = express(),
8
    port = process.env.PORT || 3001;
9
10
//Connect to the database
11
mongoose.connect('mongodb://localhost:27017/chat');
12
var db = mongoose.connection;
13
14
mongoose.set('debug', true);
15
16
db.on('error', console.error.bind(console, '# Mongo DB: connection error:'));

Includiamo mongoose con require('mongoose') e utilizziamo quindi la nostra connessione al database attraverso mongoose.connect('mongodb://localhost:27017/chat');

/chat definisce il nome del database a cui ci stiamo connettendo.

Poi, a fini di sviluppo, raccomandiamo di impostare il debugging su on.

1
mongoose.set('debug', true);

Infine aggiungiamo un handler per gli eventi d'errore:

1
db.on('error', console.error.bind(console, '# Mongo DB: connection error:'));

Quindi potete aggiungere il controllo per la connessione con il codice seguente:

1
db.once('open', function (callback) {
2
  console.log("# Mongo DB:  Connected to server");
3
}

mongoose viene usato in modo che una volta che l'istanza db riceve l'evento open, inizieremo l'esecuzione della nostra connessione mongo. Avremo così bisogno di inserire il nostro codice esistente in questa nuova connessione mongo in modo da utilizzarla.

Ecco un elenco di codice intero con l'aggiunta di mongoose e l'inserimento di righe e loro cancellazione quando gli utenti sono online e offline.

1
2
//Configure our Services
3
var PeerServer = require('peer').PeerServer,
4
    express = require('express'),
5
    mongoose = require('mongoose'),
6
    assert = require('assert'),
7
    events = require('./src/events.js'),
8
    app = express(),
9
    port = process.env.PORT || 3001;
10
11
//Tell express to use the 'src' directory
12
app.use(express.static(__dirname + '/src'));
13
14
//Connect to the database
15
mongoose.connect('mongodb://localhost:27017/chat');
16
var db = mongoose.connection;
17
18
mongoose.set('debug', true);
19
20
db.on('error', console.error.bind(console, '# Mongo DB: connection error:'));
21
22
db.once('open', function (callback) {
23
24
  console.log("# Mongo DB:  Connected to server");
25
26
  //Setup our User Schema
27
  var usersSchema = mongoose.Schema({username: String});
28
  var User = mongoose.model('User', usersSchema);
29
30
  //Configure the http server and PeerJS Server
31
  var expressServer = app.listen(port);
32
  var io = require('socket.io').listen(expressServer);
33
  var peer = new PeerServer({ port: 9000, path: '/chat' });
34
35
  //Print some console output
36
  console.log('#### -- Server Running -- ####');
37
  console.log('# Express:   Listening on port', port);
38
39
  peer.on('connection', function (id) {
40
    io.emit(events.CONNECT, id);
41
    console.log('# Connected: ', id);
42
43
    //Store Peer in database
44
    var user = new User({ username: id });
45
    user.save(function (err, user) {
46
      if (err) return console.error(err);
47
      console.log('# User '+ id + ' saved to database');
48
    });
49
50
  });
51
52
  peer.on('disconnect', function (id) {
53
    io.emit(events.DISCONNECT, id);
54
    console.log('# Disconnected: ', id);
55
56
    //Remove Peer from database
57
    User.remove({username: id}, function(err){ if(err) return console.error(err)});
58
59
  });
60
61
});

Per vederlo funzionante avviamo l'applicazione chat. Eseguiamo npm start.

Ora connettiamoci alla chat nel browser come di consueto (default http://localhost:3001).

Una volta connessi alla chat in una nuova finestra di terminale eseguite mongo chat per aprire la cli di mongo.

1
$ mongo chat
2
MongoDB shell version: 2.0.6
3
connecting to: chat
4
> db.users.find()
5
{ "username" : "CameronLovesPigs", "_id" : ObjectId("5636e9d7bd4533d610040730"), "__v" : 0 }

Qui avete il registro dei documenti archiviati in mongo, e ora potete sempre controllare quanti utenti sono online eseguendo nel prompt mongo db.users.count().

1
> db.users.count()
2
3

Aggiungere Sessioni all'Applicazione

Dal momento che abbiamo usato Express per sviluppare l'applicazione, questa parte sarà davvero molto facile e richiederà l'installazione di un paio di moduli da npm per permetterci di proseguire.

Prendete i pacchetti express-session e connect-mongo da npm:

1
$ npm install express-session connect-mongo cookie-parser --save

Ora includeteli all'inizio di app.js:

1
var PeerServer = require('peer').PeerServer,
2
    cookieParser = require('cookie-parser'),
3
    express = require('express'),
4
    session = require('express-session'),
5
    mongoose = require('mongoose'),
6
    MongoStore = require('connect-mongo')(session),
7
    //...

Dopo che avete impostato mongoose.connect potete configurare le sessioni con express. Cambiate il vostro codice nel modo seguente; potete specificare la vostra stringa secret.

1
//Connect to the database
2
mongoose.connect('mongodb://localhost:27017/chat');
3
var db = mongoose.connection;
4
5
mongoose.set('debug', true);
6
7
db.on('error', console.error.bind(console, '# Mongo DB: connection error:'));
8
9
app.use(cookieParser());
10
app.use(session({
11
  secret: 'supersecretstring12345!',
12
  saveUninitialized: true,
13
  resave: true,
14
  store: new MongoStore({ mongooseConnection: db })
15
}))

Qui un'impostazione cruciale da notare è saveUninitialized: true dentro l'ultimo app.use. Assicurerà che le sessioni vengano salvate.

Specifichiamo dove grazie alla proprietà store, che impostiamo nell'istanza MongoStore indicando quale connessione usare attraverso mongooseConnection e il nostro oggetto db.

Per archiviare la sessione abbiamo bisogno di usare express per la gestione della richiesta perché abbiamo bisogno di accedere al valore della richiesta, ad esempio:

1
//Start persistent session for user
2
app.use(function(req, res, next) {
3
  req.session.username = id;
4
	req.session.save();

Ciò creerà la variabile req.session.username con il valore inserito dall'utente e lo salveremo per utilizzo successivo.

Poi potremo cercare questo valore con il codice lato client ed effettuare il log in automatico dell'utente quando aggiorna, cosicché non venga mai escluso dalla chat ed esegua automaticamente il login con l'username scelto. 

Interessante anche notare che, dal momento che abbiamo delle sessioni supportate da database, nel caso che gli sviluppatori cambino l'applicazione e il back-end venga ricaricato, gli utenti che hanno già effettuato il login rimarranno loggati essendo ora la sessione d'archiviazione persistente. Questa è una grande funzionalità per tenere i vostri utenti contenti e loggati mentre state sviluppando, o se è presente una disconnessione da un client non stabile.

Login persistente

Ora che abbiamo la sessione cookie impostata, lavoriamo sull'aggiungere il login persistente al nostro codice front-end.

Finora abbiamo solo usato il route di default fornito da Express per un'applicazione SPA, e non abbiamo definito alcuna gestione routing per Express. Come menzionato prima, per avere accesso alla sessione avrete bisogno delle variabili di richiesta / risposta di Express.

Prima di tutto abbiamo bisogno di una route in modo da accedere all'oggetto request fornito da Express e visualizzarlo per il debug. All'interno del file di configurazione Express /app.js, aggiungete le righe seguenti all'inizio del file, dopo il setup della sessione:

1
app.use(session({
2
  secret: 'supersecretstring12345!',
3
  saveUninitialized: true,
4
  resave: true,
5
  store: new MongoStore({ mongooseConnection: db })
6
}))
7
8
app.get('/', function (req, res) {
9
  res.sendFile(__dirname +'/src/index.html');
10
  if(req.session.username == undefined){
11
    console.log("# Username not set in session yet");
12
  } else {
13
    console.log("# Username from session: "+ req.session.username);
14
15
  }
16
});

Ora abbiamo qualche registrazione di base per vedere cosa sta succedendo con il nostro valore di sessione. Per impostarlo, abbiamo bisogno di configurare le routes get e set nel modo seguente:

1
//Save the username when the user posts the set username form
2
app.post('/username', function(req, res){
3
  console.log("# Username set to "+ req.body.username);
4
  req.session.username = req.body.username;
5
  req.session.save();
6
  console.log("# Session value set "+ req.session.username);
7
  res.end();
8
});
9
10
//Return the session value when the client checks
11
app.get('/username', function(req,res){
12
  console.log("# Client Username check "+ req.session.username);
13
  res.json({username: req.session.username})
14
});

Queste due routes funzioneranno come il get e il set per la variabile di sessione username. Ora con un po' di semplice JavaScript possiamo implementare l'autologin per la nostra applicazione. Aprite src/App.js e modificatelo nel modo seguente:

1
/* global EventEmitter, events, io, Peer */
2
/** @jsx React.DOM */
3
4
$(function () {
5
  'use strict';
6
7
  // Check for session value
8
  $(document).ready(function(){
9
    $.ajax({
10
          url: '/username'
11
    }).done(function (data) {
12
      console.log("data loaded: " + data.username);
13
      if(data.username)
14
        initChat($('#container')[0], data.username);
15
    });
16
  });
17
18
  // Set the session
19
  $('#connect-btn').click(function(){
20
    var data = JSON.stringify({username: $('#username-input').val()});
21
    $.ajax({ url: '/username',
22
              method: "POST",
23
              data: data,
24
              contentType: 'application/json',
25
              dataType: 'json'
26
            });
27
  });
28
29
  // Initialize the chat
30
  $('#connect-btn').click(function () {
31
    initChat($('#container')[0],
32
      $('#username-input').val());
33
  });
34
35
  function initChat(container, username) {
36
    var proxy = new ChatServer();
37
    React.renderComponent(<ChatBox chatProxy={proxy}
38
      username={username}></ChatBox>, container);
39
  }
40
41
  window.onbeforeunload = function () {
42
    return 'Are you sure you want to leave the chat?';
43
  };
44
45
});

Con il servizio $.ajax di jQuery creiamo una richiesta per controllare il valore della variabile di sessione quando document diventa disponibile. Se è impostato inizializziamo quindi il nostro componente React con il valore archiviato, risultante in una funzionalità autologin per gli utenti.

Avviate nuovamente la chat con npm start e guardate nel browser le sessioni funzionanti.

Conclusioni

Ora avete visto quanto è facile usare Mongoose insieme a Express e impostare le sessioni Express. Approfondendo ulteriormente lo sviluppo dell'applicazione, con React come view controller collegato agli elementi del database creerete applicazioni interessanti.

Se volete procedere ulteriormente con React e guardare come i componenti possono comunicare tra l'uno e l'altro internamente attraverso il framework, questa guida dalla documentazione ufficiale vi risulterà molto utile.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.