Crea Projecto de React TypeScript con Express.js TypeScript
Tags: react, javascript, typescript, spanish
Published: 2022-07-10 20:29:00

Hola 👋🏼, vamos a construir un formulario de inicio de sesión con React TypeScript desde un servidor Express.js con TypeScript. No nos vamos a enfocar en cómo construir un sistema de inicio de sesión; en su lugar, vamos a trabajar en la integración de TypeScript y el servidor. Debido a la complejidad de este tutorial, te dejo aquí el link de mi website; Tiene mejores representaciones visuales que aquí.

{% embed https://codingpr.com/es/react-typescript-y-express/ %}

## 1. Configure su entorno de Node.

- Cree un nuevo directorio en su computadora y vaya a ese directorio.

```bash
Terminal

    mkdir simple-react-form
    cd simple-react-form
```

- Cree un proyecto Node.js, use el indicador -y para crearlo sin hacer preguntas y abre el proyecto en tu editor de código favorito. Vaya a package.json y complete los valores vacíos.

```bash
Terminal

    npm init -y
    code .
```

## 2. Configurar Express.js y TypeScript.

- Instale cors, dotenv y express.js. Cors habilitará las solicitudes HTTP desde afuera de nuestro puerto de servidor. Dotenv nos permitirá usar variables de ambiente.

```bash
Install through npm or yarn

    npm install cors dotenv express
```
- A continuación, instale todas las librerías relacionadas a TypeScript con el indicador -D (desarrollo). El concurrently nos permitirá ejecutar varios comandos en scripts de package.json. El nodemon reiniciará automáticamente el servidor cuando realicemos cambios en cualquier archivo del directorio.

```bash
npm install -D typescript @types/cors @types/express @types/node concurrently nodemon
```

- Cree el archivo de configuración de TypeScript con el siguiente comando.

```bash
Config

    npx tsc --init
```

- En el archivo tsconfig.json, descomente y agregue estos valores JSON.

```json
tsconfig.json

    {
      "compilerOptions": {
        "target": "es2016",
        "jsx": "preserve",
        "module": "commonjs",
        "allowJs": true,
        "outDir": "./dist",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true
      },
      "exclude": [
        "client",
        "dist",
        "node_modules"
      ]
    }
```

- A continuación, vaya a package.json y actualice la sección de scripts.

```json
package.json

    {
      "scripts": {
        "build": "npx tsc",
        "start": "node dist/index.js",
        "dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/index.js\"",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
    }
```
- Cree index.ts en la raíz del proyecto e inserte el siguiente código.

```javascript
index.ts

    import dotenv from "dotenv";
    import express, { Express, Request, Response } from "express";
    import path from "path";
    import cors from "cors";

    dotenv.config();

    const app: Express = express();

    app.use(express.json());
    app.use(cors());

    app.get('/', (req: Request, res: Response) => {
      res.send('<h1>Hello World From the Typescript Server!</h1>')
    });

    const port = process.env.PORT || 8000;

    app.listen(port, () => {
      console.log(`Example app listening on port ${port}`)
    }); 
```

- Reinicie su editor si está usando VS Code, abra su terminal nuevamente y ejecute:

```bash
Terminal

    npm run build
    npm run dev
```
## 3. Configurar React y TypeScript.

- Ahora es el momento de construir nuestro lado 'client' React. Primero, abra su terminal de comando, asegúrese de estar en la raíz del proyecto, e instale React con TypeScript con el nombre de client.

```bash
Terminal

    npx create-react-app client --template typescript
```

- Elimine la carpeta git que React instala de forma predeterminada.

```bash
Git Bash

    $ cd client
    $ rm -rf .git
```
- Vaya a la carpeta src y cree dos carpetas: components y utils.

```bash
Git Bash

    $ cd src
    $ mkdir components
    $ mkdir utils
```

- Dentro de la carpeta de componentes crea otra carpeta llamada form-input, luego, cree form-input.tsx y copie el código de abajo; este archivo contendrá nuestras entradas de formulario reutilizables (input forms). Si quieres manipular el estilo del 'input form', crea form-input.css en la carpeta 'from-input'.

```bash
Git Bash

    $ cd components
    $ mkdir form-input
    $ cd form-input
    $ touch form-input.tsx
```
```javascript
client/src/components/form-input/form-input.tsx

    import { InputHTMLAttributes, FC } from "react";

    import './form-input.css';

    type FromInputProps = { label: string } &
      InputHTMLAttributes<HTMLInputElement>;

    const FormInput: FC<FromInputProps> = ({ label, ...otherProps }) => {
      return (
        <div className="group">
          <input {...otherProps} />
          {
            label &&
            <div className="form-input-label">
              {label}
            </div>
          }
        </div>
      );
    }

    export default FormInput;
```

- Cree una carpeta utils y agregue data-utils.ts; este archivo hará las llamadas API al servidor.

```javascript
client/src/utils/data-utils.ts

    export const getData = async <T>(
      url: string,
      email: string,
      password: string
    )
    : Promise<T> => {
      const res = await fetch(url, {
        method: 'Post',
        headers: {
          'Content-type': 'application/json'
        },
        body: JSON.stringify({ email, password })
      });

      return await res.json();
    }
```
- Modifica el archivo app.tsx; estaremos construyendo el formulario de inicio de sesión usando las mismas clases y colores de React.

```javascript
client/src/App.tsx

    import { useState, ChangeEvent, FormEvent } from "react";
    import { ReactComponent as Logo } from "./logo.svg";
    import { getData } from "./utils/data-utils";
    import FormInput from './components/form-input/form-input';

    import './App.css';

    // declaraciones TypeScript
    type User = {
      id: number,
      name: string,
      email: string,
      password: string
    }

    const defaultFormFields = {
      email: '',
      password: '',
    }

    const App = () => {
      // react hooks
      const [user, setUser] = useState<User | null>()
      const [formFields, setFormFields] = useState(defaultFormFields)
      const { email, password } = formFields

      const resetFormFields = () => {
        return (
          setFormFields(defaultFormFields)
        );
      }

      // handle input
      const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
        const { name, value } = event.target
        setFormFields({...formFields, [name]: value })
      }

      const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault()

        try {
          // Llamada API
          const res:User = await getData(
            'http://localhost:8000/login', email, password
          )
          setUser(res);
          resetFormFields()
        } catch (error) {
          alert('User Sign In Failed');
        }
      };

      const reload = () => {
        setUser(null);
        resetFormFields()
      };

      return (
        <div className='App-header'>
          <h1>
            { user && `Welcome! ${user.name}`}
          </h1>
          <div className="card">
            <Logo className="logo" />
            <h2>Sign In</h2>
            <form onSubmit={handleSubmit}>
              <FormInput
                label="Email"
                type="email"
                required
                name="email"
                value={email}
                onChange={handleChange}
              />
              <FormInput
                label="Password"
                type='password'
                required
                name='password'
                value={password}
                onChange={handleChange}
              />
              <div className="button-group">
                <button type="submit">Sign In</button>
                <span>
                  <button type="button" onClick={reload}>Clear</button>
                </span>
              </div>
            </form>
          </div>
        </div>
      );
    }

    export default App;
```
## 4. Agrega nuevas rutas y TypeScript al servidor.

- Estamos casi terminando. Vuelva a index.ts y agregue la ruta de inicio de sesión con TypeScript adicional.

```javascript
index.ts

    interface FormInputs {
      email: string,
      password: string
    }

    // Array de usuarios con fines de prueba
    const users = [
      {
        id: 1,
        name: 'Maria Doe',
        email: 'maria@example.com',
        password: 'maria123'
      },
      {
        id: 2,
        name: 'Juan Doe',
        email: 'juan@example.com',
        password: 'juan123'
      }
    ];

    // route login
    app.post('/login', (req: Request, res: Response) => {
      const { email, password }:FormInputs = req.body;

      const user = users.find(user => {
        return user.email === email && user.password === password
      });

      if (!user) {
        return res.status(404).send('User Not Found!')
      }

      return res.status(200).json(user)
    });

```
- Ejecute tanto el cliente como el servidor en terminales individuales.

```bash
Terminal

    npm run dev
    cd client
    npm start
```
- Inicie las pruebas de su aplicación.
- Consulte la segunda parte de este tutorial.
[Cómo subir un proyecto de React y Express TypeScript a Heroku](https://codingpr.com/es/lanzamiento-de-projecto-express/).