Authenticación 🔑

Hasta este punto solo hemos estado en comunicación con nuestra API por medio de GET, en esta sección vamos a utilizar el metodo POST para crear nuevos usuarios.

Componente de Registro

Lo primero que vamos hacer es crear un nuevo componente llamado Register.jsx en nuestra carpeta components

src/components/Register.jsx
import React from 'react';

const Register = () => (
  <form className="user">
    <div className="form-group row">
      <div className="col-sm-6 mb-3 mb-sm-0">
        <input type="text" className="form-control form-control-user" id="exampleFirstName" placeholder="First Name" />
      </div>
      <div className="col-sm-6">
        <input type="text" className="form-control form-control-user" id="exampleLastName" placeholder="Last Name" />
      </div>
    </div>
    <div className="form-group">
      <input type="email" className="form-control form-control-user" id="exampleInputEmail" placeholder="Email Address" />
    </div>
    <div className="form-group row">
      <div className="col-sm-6 mb-3 mb-sm-0">
        <input type="password" className="form-control form-control-user" id="exampleInputPassword" placeholder="Password" />
      </div>
      <div className="col-sm-6">
        <input type="password" className="form-control form-control-user" id="exampleRepeatPassword" placeholder="Repeat Password" />
      </div>
    </div>
    <button type="submit" className="btn btn-primary btn-user btn-block">
      Register Account
    </button>
  </form>
);

export default Register;

Actualizar la pagina de Registro

Luego de esto, vamos actualizar la pagina de registro para usar este componente que acabamos de crear y remover todo el html del formulario que allí tenemos.

src/pages/Register.jsx
import React from 'react';
import { Link } from 'react-router-dom';

// Agregamos el componente que acabamos de crear
import FormRegister from '../components/Register';

const Register = () => (
  <div className="container">
    <div className="card o-hidden border-0 shadow-lg my-5">
      <div className="card-body p-0">
        <div className="row">
          <div className="col-lg-5 d-none d-lg-block bg-register-image" />
          <div className="col-lg-7">
            <div className="p-5">
              <div className="text-center">
                <h1 className="h4 text-gray-900 mb-4">Create an Account!</h1>
              </div>
              {/* Remplazamos todo el html del formulario por el componente */}
              <FormRegister />
              <hr />
              <div className="text-center">
                <Link className="small" to="/login">Already have an account? Login!</Link>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
);

export default Register;

Nota: Comprobar que tu pagina se ve igual con este cambio, ve a tu navegador a la url http://localhost:3000/register

Obtener los datos del formulario

Ahora vamos a conectar los datos de nuestro formulario para enviarlos a la API y crear un nuevo usuario en el sistema.

La primero será capturar los datos de nuestros input, para eso vamos a utilizar el hook useState:

src/components/Register.jsx
// Agregar useState
import React, { useState } from 'react';

const Register = () => {
  // Inicializar nuestro estado interno
  const [form, setForm] = useState({});
  
  return (
    <form className="user">
      {/* ... Codigo del formulario */}
    </form>
  );
}

export default Register;

Continuaremos ahora con la función que se encargará de actualizar nuestro estado interno, cada que el input tenga un cambio.

src/components/Register.jsx
import React, { useState } from 'react';

const Register = ({ handleSumbit }) => {
  const [form, setForm] = useState({});
  
  
  // Funcion para actualizar cada uno de los input 
  const handleInputChange = (evt) => {
    const { target: { name, value } } = evt;

    setForm({ [name]: value, ...form });
  }

  return (
    <form className="user" onSubmit={sendForm}>
      <div className="form-group row">
        <div className="col-sm-6 mb-3 mb-sm-0">
          {/* Vamos agregar la funcion handleInputChange con callback del onChange */}
          <input
            type="text"
            className="form-control form-control-user"
            id="firstName"
            placeholder="First Name"
            name="name"
            onChange={handleInputChange}
            required
          />
        </div>
        <div className="col-sm-6">
          {/* Vamos agregar la funcion handleInputChange con callback del onChange */}
          <input
            type="text"
            className="form-control form-control-user"
            id="lastName"
            placeholder="Last Name"
            name="lastName"
            onChange={handleInputChange}
            required
          />
        </div>
      </div>
      <div className="form-group">
        {/* Vamos agregar la funcion handleInputChange con callback del onChange */}
        <input
          type="email"
          className="form-control form-control-user"
          id="email"
          placeholder="Email Address"
          name="email"
          onChange={handleInputChange}
          required
        />
      </div>
      <div className="form-group row">
        <div className="col-sm-6 mb-3 mb-sm-0">
          {/* Vamos agregar la funcion handleInputChange con callback del onChange */}
          <input
            type="password"
            className="form-control form-control-user"
            id="password"
            placeholder="Password"
            name="password"
            onChange={handleInputChange}
            required
          />
        </div>
        <div className="col-sm-6">
          {/* Vamos agregar la funcion handleInputChange con callback del onChange */}
          <input
            type="password"
            className="form-control form-control-user"
            id="confirmPassword"
            placeholder="Repeat Password"
            name="confirmPassword"
            onChange={handleInputChange}
            required
          />
        </div>
      </div>
      <button type="submit" className="btn btn-primary btn-user btn-block">
        Register Account
      </button>
    </form>
  );
}

export default Register;

Ahora solo nos falta tener la función que se ejecutara cuando le demos clic en el boton tipo submit, vamos a crear la siguiente función, justo debajo handleInputChange.

src/components/Register.jsx
const sendForm = (evt) => {
  evt.preventDefault();
  // Vamos a ejecutar un callback que nos llegará como prop.
  console.log(form);
}

Finalmente todo el componente Register.jsx debe verse de la siguiente forma:

src/components/Register.jsx
import React, { useState } from 'react';

const Register = ({ handleSumbit }) => {
  const [form, setForm] = useState({});

  const handleInputChange = (evt) => {
    const { target: { name, value } } = evt;

    setForm({ [name]: value, ...form });
  }

  const sendForm = (evt) => {
    evt.preventDefault();
    handleSumbit(form);
  }

  return (
    <form className="user" onSubmit={sendForm}>
      <div className="form-group row">
        <div className="col-sm-6 mb-3 mb-sm-0">
          {/*  */}
          <input
            type="text"
            className="form-control form-control-user"
            id="firstName"
            placeholder="First Name"
            name="name"
            onChange={handleInputChange}
            required
          />
        </div>
        <div className="col-sm-6">
          <input
            type="text"
            className="form-control form-control-user"
            id="lastName"
            placeholder="Last Name"
            name="lastName"
            onChange={handleInputChange}
            required
          />
        </div>
      </div>
      <div className="form-group">
        <input
          type="email"
          className="form-control form-control-user"
          id="email"
          placeholder="Email Address"
          name="email"
          onChange={handleInputChange}
          required
        />
      </div>
      <div className="form-group row">
        <div className="col-sm-6 mb-3 mb-sm-0">
          <input
            type="password"
            className="form-control form-control-user"
            id="password"
            placeholder="Password"
            name="password"
            onChange={handleInputChange}
            required
          />
        </div>
        <div className="col-sm-6">
          <input
            type="password"
            className="form-control form-control-user"
            id="confirmPassword"
            placeholder="Repeat Password"
            name="confirmPassword"
            onChange={handleInputChange}
            required
          />
        </div>
      </div>
      <button type="submit" className="btn btn-primary btn-user btn-block">
        Register Account
      </button>
    </form>
  );
}

export default Register;

Registrar Usuario

En nuestra pagina de registro vamos ahora agregar el código necesario para llamar a nuestro endpoint api/users y crear un nuevo usuario.

src/pages/Register.jsx
const API = 'https://shopping-cart-api.khriztianmoreno.now.sh/api/users';

const createUser = async(form) => {
  const payload = {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(form),
  };

  try {
    const result = await fetch(API, payload);
    const user = await result.json();
    if (user && user.token) {
      localStorage.setItem('userEco', JSON.stringify(user))
    }
  } catch (error) {
    console.error('Error :(', error);
  }
}

Finalmente vamos a pasar esta función como prop a nuestro componente FormRegister. Finalmente veremos la pagina de registro con el siguiente código:

src/pages/Register.jsx
import React from 'react';
import { Link, withRouter } from 'react-router-dom';

import FormRegister from '../components/Register';

const API = 'https://shopping-cart-api.khriztianmoreno.now.sh/api/users';

const createUser = async(form) => {
  const payload = {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(form),
  };

  try {
    const result = await fetch(API, payload);
    const user = await result.json();
    if (user && user.token) {
      localStorage.setItem('userEco', JSON.stringify(user))
    }
  } catch (error) {
    console.error('Error :(', error);
  }
}

const Register = () => (
  <div className="container">
    <div className="card o-hidden border-0 shadow-lg my-5">
      <div className="card-body p-0">
        <div className="row">
          <div className="col-lg-5 d-none d-lg-block bg-register-image" />
          <div className="col-lg-7">
            <div className="p-5">
              <div className="text-center">
                <h1 className="h4 text-gray-900 mb-4">Create an Account!</h1>
              </div>
              <FormRegister handleSumbit={createUser} />
              <hr />
              <div className="text-center">
                <Link className="small" to="/login">Already have an account? Login!</Link>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
);

export default withRouter(Register);

En este punto si vamos a nuestro navegador y registrar un usuario por medio de la url http://localhost:3000/register deberas ver por medio de las developer tools de tu navegador el token del usuario almacenado en el localstorage.

Código de referencia: En este enlace puedes ver el commit correspondiente a este punto Github.

Retos

  1. Actualizar el codigo de la pagina de registro para redireccionar al usuario a la pagina principal luego de ser registrado en el sistema.

  2. Crear la funcionalidad para hacer login en el sistema.

Last updated