Se requiere una interfaz de usuario con tres campos de entrada de texto y una etiqueta de texto. La etiqueta debe mostrar en tiempo real la suma de los números ingresados en los campos. Si algún valorr no es un número válido, se considerará como cero. Los valores iniciales de los campos son 1, 2 y 3 respectivamente.
Configuración del Proyecto
# Instalar la herramienta CLI
$ npm install -g create-react-app
# Crear una nueva aplicación llamada MiAplicacionRx
$ create-react-app mi-aplicacion-rx --scripts-version=react-scripts-ts
$ cd mi-aplicacion-rx
$ npm start
En un IDE como IntelliJ IDEA, importar el proyecto desde el directorio existente. Configurar una ejecución npm para iniciar el servidor de desarrollo. Accceder a la aplicación en http://localhost:3000/.
Configuración de TSLint
Modificar el archivo tslint.json para deshabilitar reglas específicas que puedan interferir con el desarrollo.
{
"extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
"linterOptions": {
"exclude": [
"config/**/*.js",
"node_modules/**/*.ts",
"coverage/lcov-report/*.js"
]
},
"rules": {
"interface-name": false,
"ordered-imports": false,
"no-console": false,
"object-literal-sort-keys": false,
"member-access": false,
"variable-name": false,
"member-ordering": false,
"class-name": false
}
}
Estilos CSS
Añadir estilos para los campos de entrada numérica en App.css.
.campo-numerico {
width: 50px;
text-align: right;
}
Implementación sin RxJS
Utilizar el estado de React para manejar las entradas y calcular la suma directamente.
import './App.css';
import React from 'react';
class FormularioCalculadora extends React.Component {
state = {
valor1: '1',
valor2: '2',
valor3: '3',
total: '',
};
componentDidMount() {
this.calcularSuma();
}
render() {
return (
<div classname="App">
<p>
<input classname="campo-numerico" name="valor1" onchange="{this.manejarCambio}" value="{this.state.valor1}"></input> +
<input classname="campo-numerico" name="valor2" onchange="{this.manejarCambio}" value="{this.state.valor2}"></input> +
<input classname="campo-numerico" name="valor3" onchange="{this.manejarCambio}" value="{this.state.valor3}"></input> =
<label>{this.state.total}</label>
</p>
</div>
);
}
manejarCambio = (evento: React.ChangeEvent<HTMLInputElement>) => {
const nombreCampo = evento.target.name;
const valorCampo = evento.target.value;
this.setState({ [nombreCampo]: valorCampo }, () => this.calcularSuma());
};
calcularSuma = () => {
const convertirNumero = (cadena: string) => Number(cadena) || 0;
const suma = convertirNumero(this.state.valor1) + convertirNumero(this.state.valor2) + convertirNumero(this.state.valor3);
this.setState({ total: String(suma) });
};
}
export default FormularioCalculadora;
Implementación con RxJS
Emplear observables de RxJS para reaccionar a los cambios de entrada de forma reactiva.
import './App.css';
import React from 'react';
import { combineLatest, fromEvent, Observable } from 'rxjs';
import { map, pluck, startWith } from 'rxjs/operators';
class FormularioReactive extends React.Component {
state = {
resultado: '',
};
componentDidMount() {
const crearFlujoEntrada = (idElemento: string) => {
const elemento = document.getElementById(idElemento) as HTMLInputElement;
return fromEvent(elemento, 'input').pipe(
pluck('target', 'value'),
startWith(elemento.value)
) as Observable<string>;
};
const aNumero = (texto: string) => Number(texto) || 0;
const flujoSuma = combineLatest(
crearFlujoEntrada('campo1'),
crearFlujoEntrada('campo2'),
crearFlujoEntrada('campo3')
).pipe(
map((valores: string[]) => {
const num1 = aNumero(valores[0]);
const num2 = aNumero(valores[1]);
const num3 = aNumero(valores[2]);
return String(num1 + num2 + num3);
})
);
flujoSuma.subscribe(valor => this.setState({ resultado: valor }));
}
render() {
return (
<div classname="App">
<p>
<input classname="campo-numerico" defaultvalue="1" id="campo1"></input> +
<input classname="campo-numerico" defaultvalue="2" id="campo2"></input> +
<input classname="campo-numerico" defaultvalue="3" id="campo3"></input> =
<label>{this.state.resultado}</label>
</p>
</div>
);
}
}
export default FormularioReactive;