Introducción
Construiremos una aplicación de chat sencilla con ReactJS basada en el servidor que ya implementamos. Comenzamos creando componentes estáticos, que luego se conectan al estado. Finalmente, nos suscribimos al servidor de eventos.
Requisitos previos
- Conocimientos básicos de JavaScript y ReactJS (estoy tratando de mantener las cosas simples)
- npm v6
- npx v6
- nodo v12
Paso 1: Lanzar el proyecto
En la carpeta de tu proyecto, ejecuta npx create-react-app --use-npm simple-chat-app y espera a que finalice la instalación. Esto agregará todas las dependencias necesarias y te proporcionará una experiencia de desarrollo y compilación sencilla.
Agregue los siguientes archivos a la carpeta src:
- App.js (ya debería existir)
- ChatLineHolder.js
- ChatLine.js
- ChatInput.js
Ejecute npm run start desde la carpeta del proyecto en su consola. Esto iniciará un servidor de desarrollo y abrirá la aplicación en su navegador predeterminado.
Ya debería haber un archivo App.js en tu carpeta src. Por ahora, puedes eliminar todo lo que devuelve y solo tener uno. <div> Devuélvelo.
const App = () => {
return <div className='chat-app'></div>
}Comenzamos creando nuestros componentes desde abajo hacia arriba.
Paso 2: Componente
En ChatLine.js creamos un nuevo componente que tiene dos propiedades:
nombre: cadenamensaje: cadena
Estos son los datos que recibiremos más tarde del servidor como datos del evento.
Componente uno
import React from 'react'
const ChatLine = ({ name, message }) => {
return (
<li>
{name}: {message}
</li>
)
}
export defaultNota: ReactJS previene automáticamente la inyección de HTML, por lo que no necesita preocuparse por ello.
Paso 3: Componente
En ChatHolder.js creamos un nuevo componente que solo toma una base:
Líneas: Array<{ nombre: cadena, mensaje: cadena }>
Si pauta Si está vacío, mostramos una notificación sencilla.
if (lines.length === 0) {
return <div>Chat history is empty</div>
}Líneas es un array de objetos. Cada objeto tiene un nombre y un mensaje de propiedad. Mapeamos todos los elementos del array para obtener el resultado pasando el nombre y la cadena al componente. Vamos a crear múltiples nodos ChatLine.
const chatLines = lines.map(
(line, index) => (
<ChatLine key={index} name={line.name} message={line.message} />
)
)Entonces el resultado en un
- Renderizamos y nos quedamos con el componente terminado:
- onSend: (mensaje: cadena) => void
- nombre: El nombre del usuario que está chateando.
- chatLines: una matriz que representa el historial de chat.
- eventLister: se utiliza para administrar eventos desde el servidor. (Nota: decidí poner el oyente en la parte.
- Enviar mensaje al servidor
- Suscribirse a los eventos enviados por el servidor
import React from 'react'
import ChatLine from './ChatLine'
const ChatLineHolder = ({ lines }) => {
if (lines.length === 0) {
return <div>Chat history is empty</div>
}
const chatLines = lines.map(
(line, index) => (
<ChatLine key={index} message={line.message} name={line.name} />
)
)
return (
<ul>
{chatLines}
</ul>
)
}
export default ChatLineHolderNota: Normalmente se usa un identificador único como clave. En este caso, podemos usar el índice con seguridad, ya que la asociación entre el índice y el objeto no cambia. En una aplicación real, esto resulta muy frustrante.
Paso 4: Componente
Como habrás notado, todavía no hay forma de importar mensajes. Gestiona la entrada de texto y utiliza una función de devolución de llamada al enviar para iniciar un nuevo mensaje de chat al hacer clic en el botón. Requiere una propiedad:
El componente de entrada del usuario mantiene su estado y administra las actualizaciones.
const [value, setValue] = useState('')
const onChange = (event) => {
setValue(event.target.value)
}Al hacer clic en el botón de envío, se llama a la función onSend con el estado actual. Como no queremos que el usuario tenga que borrar manualmente el campo de entrada, restablecemos el estado después de llamar a onSend.
const onClickSend = () => {
onSend(value)
setValue('')
}
Aquí está el componente final:
import React, { useState } from 'react'
const ChatInput = ({ onSend }) => {
const [value, setValue] = useState('')
const onChange = (event) => {
setValue(event.target.value)
}
const onClickSend = () => {
setValue('')
onSend(value)
}
return (
<div>
<input type='text' value={value} onChange={onChange} />
<button onClick={onClickSend}>send</button>
</div>
)
}
export default ChatInputPaso 5: Componente
Modo
Dado que nuestros componentes no almacenan ningún dato, Como componente principal que utilizamos para gestionar el estado, tenemos tres tipos de estados:
(Para simplificar, es posible que desees adoptar un enfoque diferente en una aplicación del mundo real).
Usamos ganchos de estado para inicializar nuestro estado:
const [chatLines, setChatLines] = useState([])
const [eventListener, setEventListener] = useState(null)
const [name] = useState(generateRandomName())Prueba de renderizado de componentes
Por ahora solo mostramos nuestro nombre y el componente. Presentamos las líneas de chat con elementos fijos. Dado que las líneas de chat son un array vacío, se debe proporcionar nuestra notificación. Llamamos a una función flash vacía para Lo enviaremos. La ejecución se realizará en el siguiente paso.
return (
<div className='chat-app'>
<h2>Chatting as {name}</h2>
<ChatLineHolder lines={chatLines} />
<ChatInput onSend={() => {}} />
</div>
)Si desea comprobar si su implementación funciona con algunos datos, simplemente agregue algunos elementos a chatLines.
const [chatLines, setChatLines] = useState([{ name: 'Thomas', 'message': 'Hi' }])
Añadir interacción
Ya podemos ingresar texto en nuestro campo de entrada de chat, pero al presionar enviar no ocurre nada. Esto se debe a que tenemos una función llamada Lo enviamos y no hace absolutamente nada. Por eso necesitamos una implementación.
Como aún no estamos conectados a nuestro servidor, implementaremos nuestro onSend para que actualice el estado directamente. Para ello, agregaremos una función auxiliar llamada addChatLine: (chatLine) => void. La usaremos más adelante para gestionar los eventos de mensajes enviados por el servidor.
const addChatLine = (chatLine) => {
setChatLines(chatLines => {
return [...chatLines, chatLine]
})
// If you don't have a lot of experience with ReactJS, just think of this as:
// setChatLines([...chatLines, chatLine])
}onSend crea un objeto de línea de chat y llama a addChatLine
const onSend = (message) => {
const chatLine = { name, message }
addChatLine(chatLine)
}No olvides enviar a Enviar.
return (
<div className='chat-app'>
<h2>Chatting as {name}</h2>
<ChatLineHolder lines={chatLines} />
<ChatInput onSend={onSend} />
</div>
)Ahora debería poder ingresar texto en el campo de entrada, hacer clic en enviar y ver su mensaje al instante.
Paso 6: Conéctese al servidor
Chatear contigo mismo es muy aburrido. Por eso necesitamos conectar nuestra aplicación al servidor. Esto se hace en dos pasos:
Enviar mensaje al servidor
Necesitamos modificar la función onSend que escribimos. Podemos reemplazar todo el cuerpo con una simple llamada fetch, que envía nuestro nombre y mensaje en el cuerpo. Es importante no llamar a addChatLine, ya que lo haremos más adelante, al recibir el evento enviado por el servidor.
const onSend = async (message) => {
fetch('http://localhost:4000/say',
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'post',
mode: 'no-cors',
body: `name=${name}&message=${message}`
})
}Si hace clic en el botón de enviar ahora, se enviará una solicitud al servidor, pero su estado aún no se actualizará. Abordaremos esto en el siguiente paso.
Suscribirse a los eventos enviados por el servidor
Antes de empezar a escuchar eventos, necesitamos una función que gestione dichos eventos de mensaje. Dado que nos conectaremos a eventos de tipo mensaje más adelante, podemos implementarla como corresponde. Simplemente toma event.data, lo convierte en un objeto y llama a addChatLine.
const onMessage = (event) => {
const chatLine = JSON.parse(event.data)
addChatLine(chatLine)
}
Para recibir eventos enviados por el servidor, creamos un objeto de la clase EventSource con nuestra dirección local. Luego, añadimos un detector de eventos para el tipo de mensaje. Después, lo envolvemos en un gancho useEffect (esto garantiza que cuando el componente... Se monta, se inicializa la fuente del evento y luego se cierra después de montarse).
useEffect(() => {
let source = new EventSource('http://localhost:4000/listen')
source.addEventListener('message', onMessage)
setEventSource(source)
return () => { source.close() }
}, [])Componente Finalmente se ve así:
import React, { useEffect, useState } from 'react'
import ChatLineHolder from './ChatLineHolder'
import ChatInput from './ChatInput'
const App = () => {
const [chatLines, setChatLines] = useState([])
const [eventSource, setEventSource] = useState(null)
const [name] = useState(generateRandomName())
const addChatLine = (chatLine) => {
setChatLines(chatLines => [...chatLines, chatLine])
}
const onMessage = (event) => {
const chatLine = JSON.parse(event.data)
addChatLine(chatLine)
}
useEffect(() => {
let source = new EventSource("http://localhost:4000/listen")
source.addEventListener('message', onMessage)
setEventSource(source)
return () => { source.close() }
}, [])
const onSend = (message) => {
fetch(
`http://localhost:4000/say`,
{
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
method: "post",
mode: 'no-cors',
body: `name=${name}&message=${message}`,
})
}
return (
<div className='chat-app'>
<h2>Chatting as {name}</h2>
<ChatLineHolder lines={chatLines} />
<ChatInput onSend={onSend} />
</div>
)
}
export default AppResultado
¡Ahora puedes abrir tu página en dos pestañas y chatear con dos alter egos! También puedes montar el componente App dos veces (modificando index.js), ya que cada instancia tiene su propio estado.









