Advertisement
  1. Code
  2. JavaScript

Creación de una aplicación web colaborativa con PubNub, React.js y ES6

Scroll to top
Read Time: 14 min

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

En mis tutoriales anteriores, demostré cómo prototipar dispositivos de Internet de las cosas, y también creé visualizaciones de datos a partir de sensores de hardware, utilizando la red de transmisión de datos de PubNub. En este tutorial, voy a mostrarte cómo usar PubNub para crear una aplicación web colaborativa en tiempo real usando React.js, que te permite manipular el DOM de manera muy eficiente y la próxima generación de JavaScript, ES6.

PubNub Reactjs Stickie Web AppPubNub Reactjs Stickie Web AppPubNub Reactjs Stickie Web App

Demostración en vivo: Stickies colaborativos

He creado dos versiones de la misma aplicación Stickie Note: la que he alojado en este CodePen usa versiones de React alojadas en CDN, y otra está en GitHub, usando gestores de paquetes. En este tutorial, uso la versión "lite" de este último. Voy a ver cómo crear la aplicación, utilizando todos los accesorios: npm, paquete web, Babel para JSX y ES6.

Requisitos previos

Para seguir, necesitarás:

  • comprensión básica de React
  • conocimiento práctico del administrador de paquetes npm para descargar, instalar y administrar dependencias
  • conocimiento práctico del generador de módulos de paquete web, para unir JavaScript y otros activos para el navegador (funciona de manera similar a un gruñido o trago)
  • Node.js y npm instalados en su máquina

Este tutorial no cubre cómo comenzar con React Sin embargo, puedes aprender más de muchos otros excelentes tutoriales de Envato Tuts +.

Que es lo que vas a hacer

Vas a construir una aplicación web simple usando PubNub ahora. PubNub es una red de flujo de datos (DSN) que proporciona una infraestructura global que le permite construir y escalar aplicaciones en tiempo real y dispositivos de IoT fácilmente. Aquí, creará "notas adhesivas" compartibles. Este es el flujo de usuario de la aplicación:

  1. Un usuario inicia sesión
  2. Tan pronto como el usuario ingrese un nombre, la aplicación recupera las últimas 50 notas, si las hay.
  3. El usuario escribe algo en el panel adhesivo y pulsa la tecla de retorno para enviarlo.
  4. La nueva nota adhesiva aparece junto con las otras notas en su navegador, así como en todos los demás navegadores de todos los usuarios que están actualmente en línea.

Ahora, empecemos!

Instalación de paquetes

En el directorio de su aplicación, ejecute npm init para configurar su archivo package.json y luego instale estos módulos.

Instale el generador de módulos de paquete web, que compila, concatena, minimiza y comprime activos estáticos para el front-end:

$ npm install webpack --save-dev

Instale el servidor web webpack para ejecutar un servidor local:
$ npm install webpack-dev-server --save-dev

Instalar complementos de animación React, React DOM y CSS:
$ npm install react react-dom react-addons-css-transition-group --save

Instale Babel para usar JSX y ES6. Vamos a escribir con ES6 (ES 2015), que es la próxima generación de JavaScript, con la ayuda de Babel, un compilador:
$ sudo npm install babel-loader babel-core babel-preset-es2015 babel-preset-react --save

Instala PubNub para comunicación en tiempo real:
$ npm install pubnub --save

Configurar la estructura de la aplicación y el servidor web

Crea la estructura de tu aplicación similar a esto:

1
├── /app
2
│   ├── app.jsx
3
│   ├── stickie.jsx
4
│   ├── stickieList.jsx
5
├── /dist
6
├── /css
7
├── /images
8
├── /node_modules
9
├── index.html
10
├── package.json
11
└── webpack.config.js

Y configure webpack.config.js:

1
var webpack = require('webpack');
2
module.exports = {
3
  entry: './app/app.jsx',
4
  output: {path: './dist', filename: 'bundle.js'},
5
  watch: true,
6
  module: {...}
7
}

Vea el archivo de configuración completo en este repositorio de GitHub.

Básicamente, está configurando un archivo de entrada (archivo de nivel superior) y el destino de salida donde están todos sus js (y .jsx) los archivos se compilarán en un solo archivo, después de ejecutar el comando webpack. Además, al establecer watch: true, se asegura de que el paquete web mire los cambios de su archivo y reconstruya su archivo de salida automáticamente.

Creando el archivo index.html

Incluya el script bundle.js en su archivo index.html:

1
<!DOCTYPE html>
2
<html>
3
  <head>
4
    <meta charset="utf-8">
5
    <title>Collaborative Stickies</title>
6
    <link rel="stylesheet" href="css/style.css" />
7
  </head>
8
  <body>
9
    <section id="container"></section>
10
    <script src="dist/bundle.js"></script>
11
  </body>
12
</html>

Además, observe el elemento con un id = "contenedor" en el cuerpo. Aquí es donde se insertará su aplicación React.

Ejecución del servidor de desarrollo de Webpack

Puede ejecutar su servidor de desarrollo con el comando,
$ ./node_modules/.bin/webpack-dev-server

O puede configurarlo en su paquete .json agregando esta línea:

1
"scripts": {
2
  "start": "webpack-dev-server"
3
},

Para que pueda ejecutar el servidor con el comando npm start en su lugar.

En su navegador, vaya a http://localhost:8080/webpack-dev-server/, y debería ver su aplicación (una página HTML en blanco hasta el momento) ejecutándose allí.

Crear componentes reactivos con ES6

Abra un nuevo archivo app.jsx en el directorio de la aplicación, como configuró para un punto de entrada en su webpack.config.js. Como puede ver en la extensión de archivo, vamos a usar la extensión de sintaxis JSX JavaScript.

Primero, importe los módulos y archivos necesarios para app.jsx:

1
import React from 'react';
2
import ReactDOM from 'react-dom';
3
import StickieList from './stickieList';
4
import 'pubnub';

La declaración de importación, recientemente introducida en ES6, se usa para importar funciones, objetos o primitivas que se han exportado desde un módulo o script externo.

Luego defina una clase, CollabStickies, que amplíe la clase React.Component, utilizando esta declaración de clase ES6. Esto es equivalente al método React.createClass con ES5:

1
class CollabStickies extends React.Component {
2
  constructor(props) {
3
    super(props);
4
    this.state = {
5
      stickieList: []
6
    }
7
  }
8
9
  componentWillMount() {
10
     // will explain later

11
  }
12
...
13
  render() {
14
    return (
15
      <div>
16
        <StickieWritable username={this.props.username} color={this.props.color} />

17
        <StickieList stickieList={this.state.stickieList} />

18
      </div>

19
    );
20
  }
21
}

En la función constructora, está configurando el estado inicial de estos datos mutables, la matriz stickieList. Actualizaremos la matriz cada vez que recibamos una nueva nota adhesiva, utilizando this.setState ().

En la función de renderizado, utilice JSX para definir elementos DOM virtuales similares a plantillas HTML. En este caso, se incluyen los componentes personalizados StickieWritable y StickieList. Puede pasar los puntales mutables y los estados a los componentes para usar. Vamos a definirlos más tarde.

Cuando construyas la aplicación, Babel transpilará toda esta sintaxis ES6 y JSX en ES5 que los navegadores pueden procesar perfectamente.

Representación del nodo DOM con enlace de datos

Con ReactDOM.render (), que viene con el paquete react-dom, renderiza el componente CollabStickies en el nodo DOM en tu HTML.

1
ReactDOM.render(
2
  <CollabStickies username={username} color={color} />,

3
  document.getElementById('container')
4
);

Aquí, notas el nombre de usuario y los accesorios de color. Esta información se usa para el componente CollabStickies y se pasa a sus componentes secundarios.

Los valores deben obtenerse del inicio de sesión del usuario; Sin embargo, para simplificar la aplicación para este ejercicio, usemos simplemente window.prompt () para obtener un nombre de usuario, y luego demos un color aleatorio de notas adhesivas cuando la aplicación se carga.

1
var username = window.prompt('Your name');
2
3
const colors = ['yellow', 'pink', 'green', 'blue', 'purple'];
4
var color = colors[~~(Math.random() * colors.length)];
The localhost Server asking for your nameThe localhost Server asking for your nameThe localhost Server asking for your name

Aunque estoy usando el cuadro de diálogo de búsqueda nativa del navegador aquí, en realidad, le recomiendo que cree otro componente de UI con funciones de inicio de sesión, o use el componente de cuadro de diálogo de terceros. Hay muchos componentes reutilizables que puede encontrar, como el Modal de UI Elemental y el Diálogo de IU de Material.

Usando PubNub para la colaboración

Ahora, vas a usar PubNub para hacer que la aplicación sea colaborativa.

PubNub es una red de flujo de datos distribuida globalmente que le permite crear aplicaciones en tiempo real fácilmente. Su característica principal, pub / sub, envía y recibe datos entre múltiples usuarios simultáneamente.

En esta aplicación, cualquier persona que "inició sesión" puede publicar mensajes en notas adhesivas y compartirlos con otros usuarios.

How PubNub WorksHow PubNub WorksHow PubNub Works

Para utilizar PubNub en su aplicación, asegúrese de que el módulo pubnub se haya instalado e importado en la parte superior de su archivo.

Inicializando PubNub

En primer lugar, debe inicializarlo para crear una instancia del objeto Pubnub. Necesitas tus claves de API durante la creación de instancias, así que regístrate en PubNub para obtener tus propias claves.

1
const publish_key =  'pub-c-1d17120...'; // your pub key

2
const subscribe_key  = 'sub-c-85bdc...'; // your sub key

3
4
const pubnub = require('pubnub').init({                         
5
  publish_key   : publish_key,
6
  subscribe_key : subscribe_key,
7
  ssl: true,
8
  uuid: username
9
});
10
11
const channel = 'stickie-notes';

Aquí, está asignando el nombre de usuario obtenido del proceso de "inicio de sesión" como un uuid, identificador único. (En este ejercicio, tomamos cualquier cadena ingresada por un usuario como un uuid, pero en realidad, usted necesita un sistema de inicio de sesión real para que cada uuid sea realmente único, ¡sin duplicaciones!)

Además, observe que estoy usando la declaración de const de ES6, en lugar de var para estos valores de constante global. En ES6, una const actúa como una variable de solo lectura y representa una referencia constante a un valor. En el último ejemplo, también verá el let recién introducido, que es una variable local de alcance de bloque.

Suscribirse a mensajes

Para crear la aplicación de notas compartidas, va a utilizar el método publish () de PubNub para enviar su nota a todo el mundo, mientras que suscribir () permite que otros usuarios reciban todas las notas. El método de suscripción () se llama automáticamente cada vez que alguien publica una nueva nota.

En su aplicación React, llamemos a subscribe () dentro de componentWillMount (), que se invoca inmediatamente antes de que se realice la representación inicial en el ciclo de vida de la aplicación.

1
componentWillMount() {
2
  pubnub.subscribe({
3
    channel: channel,
4
    restore: true,
5
    connect: () => this.connect(),
6
    message: (m) => this.success(m)
7
  });
8
}

El método de suscripción es asíncrono, y cuando cada operación se completa con éxito, se llama a la devolución de llamada. En la devolución de llamada, actualice la lista de notas adhesivas estableciendo el estado de la matriz stickieList, que se definió en el constructor al principio.

En React, la modificación de sus datos con setState actualiza automáticamente la vista.

1
success(m) { 
2
  let newList = [m].concat(this.state.stickieList);
3
  this.setState({stickieList: newList});
4
}

Estamos creando la vista (un componente UI) más adelante.

En las devoluciones de llamada de suscripción, probablemente haya notado la sintaxis de aspecto gracioso con flechas, =>. Esto se llama funciones de flecha, que tiene una sintaxis más corta que las expresiones de función de ES5. Además, esta expresión vincula léxicamente este valor. De nuevo, con Babel, ¡podemos aprovechar todo el asombroso ES6!

Además, estamos utilizando la devolución de llamada de conexión opcional al método de suscripción para recuperar "historial". Esto obtendrá datos pasados ​​cuando se establezca la conexión a PubNub por primera vez.

1
connect() { 
2
  pubnub.history({
3
    channel: channel,
4
    count: 50,
5
    callback: (m) => {
6
      m[0].reverse();
7
      for (var v of m[0]) {
8
        let newList = this.state.stickieList.concat(v);
9
        this.setState({stickieList: newList});
10
      }
11
    }
12
  });
13
}

El historial () es una parte de la función Almacenamiento y Reproducción de PubNub, y en este caso, recupera los últimos 50 mensajes de PubNub. En la devolución de llamada exitosa, actualice la vista estableciendo el estado de la matriz stickieList aquí también.

Publicar mensajes

Vamos a crear una clase, StickieWritable. Es un componente de notas adhesivas que toma la entrada del usuario.

Se traduce así:

1
render() {
2
  return (
3
    <div className={'stickie-note writable ' + this.props.color}>
4
      <textarea type='text' placeholder='Your new note...' onKeyUp={this.handleTextChange.bind(this)} />

5
    </div>  

6
  );
7
}

En el área de texto, escuche el evento onKeyUp, y cada vez que se active el evento, llame a la función handleTextChange para verificar si la tecla era una tecla return / enter. Tenga en cuenta que estoy vinculando esto al llamar a la función. A diferencia de React.createClass (), que es el método ES5 de React para crear una clase, la clase ES6 no enlaza los métodos a la instancia de un objeto, por lo que debes unirlo por ti mismo. (Hay varias maneras diferentes de lograr lo mismo).

En la función handleTextChange, publique el texto y los datos del usuario en PubNub:

1
var data = {
2
  username: this.props.username,
3
  color: this.props.color,
4
  text: e.target.value,
5
  timestamp: Date.now()
6
};
7
8
pubnub.publish({
9
  channel: channel, 
10
  message: data, 
11
  callback: e.target.value = '' // resetting the text field

12
});

Ahora, cuando un usuario escribe texto en un bloc de notas y presiona regresar, el mensaje se enviará a PubNub, y todos los demás usuarios recibirán el mensaje simultáneamente (¡dentro de ¼ de segundo!).

Crear componentes de interfaz de usuario

La interfaz de usuario de la aplicación consta de algunos componentes de la interfaz de usuario, que se parecen a esto:

PubNub Stickie Components in React AppPubNub Stickie Components in React AppPubNub Stickie Components in React App

1. CollabStickies
2. StickieWritable
3. Stickie
4. StickieList

Los componentes 1 y 2 ya se han tenido en cuenta, así que vamos a crear el componente 3, un componente individual de notas adhesivas.

Crea un nuevo archivo stickie.jsx para renderizar la UI usando JSX. A diferencia del componente StickieWritable, este es un componente de IU de solo lectura sin funcionalidad UX. Solo tiene una función render () para dibujar una nota adhesiva con texto usando datos de apoyo.

Básicamente, cada vez que el usuario recibe un mensaje nuevo de otro usuario, el mensaje se representa en un nuevo componente fijo.

1
import React from 'react';
2
import ReactDOM from 'react-dom';
3
4
export default class Stickie extends React.Component {
5
  render() {
6
    return (
7
      <div className={'stickie-note ' + this.props.color} >
8
        <p className='note'>{this.props.text}</p>

9
        <p className='username'>{this.props.username}</p>

10
      </div>  

11
    );
12
  }
13
}

A continuación, vamos a crear otro componente de UI, stickieList.jsx, que es un contenedor para este componente y contiene varias notas adhesivas juntas.

Animar componentes

Importar Stickie.jsx y todas las demás dependencias en StickieList.jsx. Aquí, estoy usando un complemento ReactCSSTransitionGroup y una fuente web personalizada.

1
import React from 'react';
2
import ReactDOM from 'react-dom';
3
import ReactCSSTransitionGroup from 'react/lib/ReactCSSTransitionGroup';
4
import Stickie from './stickie';
5
import webfontloader from 'webfontloader'

Puede instalar el cargador de fuentes web con npm:
$ npm instalar webfontloader

Luego puede cargar cualquier fuente personalizada de su elección. Puede echar un vistazo al código fuente para ver cómo se importa una fuente de Google personalizada.

En render (), use una función de flecha ES6 y map () para iterar la matriz, y use stickieList para representar cada componente Stickie que acaba de crear:

1
export default class StickieList extends React.Component {
2
  render() {
3
    let items = (this.props.stickieList || []).map((item) => 
4
      <li key={item.username + '-' + item.timestamp} >
5
        <div className="stickieWrapper">
6
          <Stickie text={item.text} color={item.color} username={item.username}/>

7
        </div>

8
      </li>);

9
10
    return (
11
      <ReactCSSTransitionGroup transitionName='animation' transitionEnterTimeout={500} transitionLeaveTimeout={500} component='ul' id="stickiesList">
12
        {items}
13
      </ReactCSSTransitionGroup>  

14
    )
15
  }
16
}

Los componentes definidos pueden ser animados usando <ReactCSSTransitionGroup>. Establezca el transitionName, que debe usar en su CSS para definir el estilo de animación. Además, observe el atributo clave en <li>. Debe usar una clave única para cada lista para animar cada componente cuando esté utilizando <ReactCSSTransitionGroup>.

React agrega nombres de clase adicionales. Por ejemplo, cuando su transitionName es 'animation', también tendrá 'animation-enter', 'animation-enter-active', 'animation-leave' y 'animation-leave-active'.

Aquí está el código en /css/style.css:

1
.animation-enter {
2
  opacity: 0.1;
3
  transform: scale(1.3);
4
  transition: all 1s ease-out;
5
 }
6
.animation-enter.animation-enter-active {
7
  opacity: 1;
8
  transform: scale(1);
9
 }
10
...

¡Ahora, acaba de crear una aplicación de colaboración en tiempo real con React y PubNub! ¡Espero que hayan disfrutado el tutorial!

PubNub Stickie app gif animationPubNub Stickie app gif animationPubNub Stickie app gif animation

Puede ver el código completo, incluido CSS, en este repositorio de GitHub. Aunque, en este tutorial, estaba usando la versión "lite", app-lite.jsx, puede echar un vistazo a app.jsx para obtener más características.

Si está interesado en crear más aplicaciones en tiempo real, como aplicaciones de chat, juegos multijugador, aplicaciones comerciales, etc., vaya a PubNub y encuentre más recursos.

¿Quieres más React?

Tenemos un curso orientado específicamente a llevar tus habilidades de React lo más lejos posible. En este curso, empezarás a crear aplicaciones web modernas con React y Redux. Comenzando de la nada, usará estas dos bibliotecas para construir una aplicación web completa.

Comenzará con la arquitectura más simple posible y construirá lentamente la aplicación, característica por característica. Aprenderá conceptos básicos como herramientas, reductores y enrutamiento. También aprenderá acerca de algunas técnicas más avanzadas, como componentes inteligentes y tontos, componentes puros y acciones asíncronas. Al final, habrá creado una aplicación completa de tarjetas didácticas para aprender por repetición espaciada.

¿Interesado? ¡Echale un vistazo!

Referencias

  • PubNub: la red global de flujo de datos en tiempo real para IoT, dispositivos móviles y aplicaciones web
  • Tutorial PubNub JavaScript SDK
  • React: una biblioteca de JavaScript para crear interfaces de usuario
  • ES6: Especificación del lenguaje ECMAScript 2015
  • webpack: Módulo constructor
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.