Chiudiamo la rubrica “Realizzare una chat con Laravel, React e Pusher“, con l’ultimo appuntamento che ci vede concludere in bellezza una chat realizzata appunto con Laravel, React e Pusher :).  

Arrivati fin qui apriamo il file resources/views/layouts/app.blade.php e aggiungiamo la seguente riga prima di chiudere il tag <body>

            <script src=”{{ asset(‘js/app.js’) }}”></script>

 

In questo modo includiamo la app React.

Andiamo ora all’interno del file resources/views/home.blade.php e e all’interno del tag con id “card-body”, prima di chiuderlo inseriamo il seguente codice

 

@if (Auth::check())

<div id=”chat” data-from='{{ Auth::id() }}’ data-to=’2′>

</div>

@endif

 

Avendo utilizzato il flow di autenticazione fornito da Laravel, possiamo utilizzare l’ helper di autenticazione, e solo se l’utente è autenticato, inseriamo un tag con id “chat”. Passiamo ora al componente React che utilizzeremo.

All’interno della cartella resources/js/components creiamo un nuovo file Chat.js. Copiamo il contenuto del file di esempio fornito da Laravel all’interno della stessa cartella (Example.js) e incolliamolo all’interno del file Chat.js. Sostituiamo la dichiarazione della classe da

 

export default class Example extends Component

 

a

 

export default class Chat extends Component

 

e implementiamo il costruttore

 

constructor(props) {

super(props);

this.state={

‘messages’: [],

};

this.mounted = false;

const { from, to } = props;

window.axios.get(`api/messages/${from}/${to}`).then((response) => {

if (this.mounted) {

this.setState({

messages: response.data,

});

}

});

};

 

Come potete notare facciamo uso della variabile axios per effettuare una chiamata di tipo GET e ottenere tutti i messaggi scambiati tra due utenti e poi inserirli nello stato del componente. I parametri che passiamo a tale chiamata sono estratti dalle proprietà del componente React, ma come otteniamo quelle proprietà? In fondo al file, sostituiamo la clausola if esistente con la seguente

 

if (document.getElementById(‘chat’)) {

const element = document.getElementById(‘chat’)

const props = Object.assign({}, element.dataset)

ReactDOM.render(<Chat {…props} />, element);

}

 

Prendiamo gli attributi “data-” dall’elemento che abbiamo definito all’interno della vista home.blade.php e li passiamo al componente, nel nostro caso l’id dell’utente autenticato e l’utente con id=2 che abbiamo inserito a scopo di test. Abbiamo anche aggiunto una variabile this.mounted per non incorrere nella situazione in cui andiamo ad aggiornare lo stato di un componente che non è più caricato in memoria.

Andiamo quindi a implementare due metodi del ciclo di vita del componente: compnentDidMount e componentWillUnmount. Nel primo andremo a impostare la variabile this.mounted a true e a mettere la pagina in ascolto del canale dell’utente.

 

componentDidMount() {

this.mounted = true;

const { from } = this.props;

window.Echo.private(`user.${from}`)

.listen(‘MessageAdded’, ({ message }) => {

const { messages } = this.state;

const newMessages = messages.slice();

newMessages.push(message);

if (this.mounted) {

this.setState({

messages: newMessages,

});

}

});

}

 

Ascoltiamo il canale con il nome dato da ‘user.’ e l’id dell’utente autenticato per messaggi del tipo MessageAdded. Quando riceviamo un messaggio, che sarà automaticamente un oggetto JS decodificato dalla rappresentazione JSON del modello del messaggio che Laravel ha pensato a propagare per noi, lo utilizziamo per accodarlo agli altri già presenti all’interno dello stato del componente. Infine aggiorniamo lo stato, tramite la funzione setState, che automaticamente farà ricaricare il componente stesso. Aggiungiamo ora anche la seconda funzione, componentWillUnmount

 

       

            componentWillUnmount() {

this.mounted = false;

}

 

Non dobbiamo far altro che ricordarci di cambiare il valore della variabile this.mounted.

L’ultimo pezzo che ci manca è la funzione render() del componente. Per semplicità non implementeremo un’interfaccia molto articolata, ma una semplice lista dei messaggi con allineamento a sinistra nel caso siano stati inviati dall’utente autenticato a destra

 

render() {

const { messages } = this.state;

const { from } = this.props;

return (

<div className=”container”>

<div className=”row justify-content-center”>

<div className=”col-md-8″>

<div className=”card”>

{messages.map((message) => {

return (

<div

style={{

textAlign: ((message.from.id == from) ? ‘left’ : ‘right’),

margin: 8,

}}

key={`${message.id}`}

>

{`${message.from.name}: ${message.text}`}

</div>

);

})}

</div>

</div>

</div>

</div>

);

}

 

Come testo metteremo sempre il nome del mittente seguito dal testo del messaggio.

 

Ricordiamoci ora di includere il componente appena creato all’interno della app React. Apriamo il file resources/js/app.js e sostituiamo la riga

 

require(‘./components/Example’);

 

con

 

require(‘./components/Chat’);

 

 

L’ultimo passaggio necessario è l’inizializzazione del componente ‘laravel-echo’ e di pusher. Andiamo quindi nel file resources/js/bootstrap.js e insertiamo il seguente codice

 

import Echo from ‘laravel-echo’

 

if (!window.Pusher) {

window.Pusher = require(‘pusher-js’);

}

 

window.Echo = new Echo({

broadcaster: ‘pusher’,

key: process.env.MIX_PUSHER_APP_KEY,

cluster: process.env.MIX_PUSHER_APP_CLUSTER,

encrypted: true

});

 

A terminale eseguiamo di nuovo il comando per compilare il bundle JS

 

 

npm run dev

 

 

Ora possiamo provare l’invio di messaggi da parte di uno o dell’altro utente con Postman e vedere come la lista dei messaggi si aggiorna man mano che effettuiamo, senza effettuare un reload della pagina stessa.

Abbiamo ora un buon punto di partenza per migliorare la chat: per esempio non mettendo un valore di default per il ricevente, creando la possibilità di chat di gruppo private e pubbliche, la gestione di eventuali allegati come immagini, video o file audio e così via.

Siamo quindi riusciti a vedere come implementare una funzionalità che potrebbe sembrare altamente complessa almeno all’inizio, abbiamo visto come può essere “una questione di meno di un’ora” per poter avere una base utile per sviluppi maggiori, utilizzando allo stesso tempo alcuni costrutti fondamentali di Laravel, quali eventi, modelli, Accessors e Mutators e il Broadcasting.

Abbiamo visto inoltre come poter introdurre React nei nostri progetti Laravel, che sta prendendo sempre più piede nel mondo del front-end e del mobile con React Native.

Speriamo vivamente ti sia piaciuta questa rubrica, ne realizzeremo delle altre! Se hai idee o vuoi fornirci spunti di vario tipo puoi scrivere a   amministrazione@laramind.com