Mudanças entre as edições de "React.js: CRUD Rest"

De Aulas
Linha 63: Linha 63:
 
import './App.css';
 
import './App.css';
  
//const server = 'https://api.arisa.com.br';
+
/**
 +
* Abaixo temos o link do nosso servidor. Como exemplo, coloquei o link
 +
* de onde coloco minhas APIs para teste no meu servidor online.
 +
*
 +
* const server = 'https://api.arisa.com.br';
 +
*
 +
* Mas para o desenvolvimenoto estou usando o localhost mesmo.
 +
*/
 
const server = 'http://localhost:8080';
 
const server = 'http://localhost:8080';
  
 
class App extends Component {
 
class App extends Component {
 +
  /**
 +
  * No constructor inicializamos nossa herança (Component) e
 +
  * instanciamos nossos estados, sendo eles: lista de usuários,
 +
  * id, nome e email referente aos campos de entrada. E o disabled
 +
  * é para desabilitarmos o campo ID quano formos alterar algum
 +
  * registro
 +
  * @param {*} props
 +
  */
 
   constructor(props) {
 
   constructor(props) {
 
     super(props);
 
     super(props);
Linha 78: Linha 93:
 
   }
 
   }
  
 +
  /** Render é onde criamos a nossa página/aplicação. */
 
   render() {
 
   render() {
 +
    // Linkamos nossos estados localmente na função
 
     const { users } = this.state;
 
     const { users } = this.state;
 
     const { user_id } = this.state;
 
     const { user_id } = this.state;
Linha 140: Linha 157:
 
   }
 
   }
  
 +
  /**
 +
  * Esse método é assincrono e é chamado depois que nossa aplicação tiver
 +
  * sido criada. Ele apenas faz chama o método get para carregar os dados
 +
  * da base de dados via serviço web.
 +
  */
 
   async componentDidMount() {
 
   async componentDidMount() {
 
     this.get();
 
     this.get();
 
   }
 
   }
  
 +
  /**
 +
  * Esse evento é chamado sempre que alterarmos alguma informação nos campos
 +
  * de entrada, de forma a atualizar também os estados
 +
  */
 
   myChangeHandler = (event) => {
 
   myChangeHandler = (event) => {
 
     let nam = event.target.name;
 
     let nam = event.target.name;
Linha 150: Linha 176:
 
   }
 
   }
  
 +
  /**
 +
  * Quando o botão gravar é clicado, o handleSubmit é chamado para tratar o evento.
 +
  * @param {*} e
 +
  * @returns
 +
  */
 
   handleSubmit = async (e) => {
 
   handleSubmit = async (e) => {
 +
    // Testamos se o Id pra gravar é válido
 
     try {
 
     try {
 
       var id = parseInt(this.state.user_id);
 
       var id = parseInt(this.state.user_id);
     } catch(error) {
+
     } catch (error) {
 
       console.error("Error :", error);
 
       console.error("Error :", error);
     }  
+
     }
 +
    // vamos garantir que seremos nós que vamos tratar esse evento
 
     e.preventDefault();
 
     e.preventDefault();
 +
    /* Pegamos nossos dados dos campos de entrada e transformamos em
 +
      uma string JSON */
 
     const data = JSON.stringify({
 
     const data = JSON.stringify({
 
       id: id,
 
       id: id,
Linha 163: Linha 198:
 
     });
 
     });
 
     try {
 
     try {
 +
      // Se o campo ID está desabilitado, então é um UPDATE. Usaremos o PUT
 +
      // Caso contrário, será usado o POST. O JSON que criamos, "data" é
 +
      // colocado no corpo da mensagem
 
       if (this.state.disabled) {
 
       if (this.state.disabled) {
 
         await axios.put(`${server}/users`, data);
 
         await axios.put(`${server}/users`, data);
Linha 169: Linha 207:
 
         await axios.post(`${server}/users`, data);
 
         await axios.post(`${server}/users`, data);
 
       }
 
       }
 +
      // Limpamos os estados
 
       this.setState({
 
       this.setState({
 
         user_id: '',
 
         user_id: '',
Linha 175: Linha 214:
 
         disabled: false,
 
         disabled: false,
 
       });
 
       });
 +
      // Atualizamos a lista da tabela
 
       this.get();
 
       this.get();
 
     } catch (error) {
 
     } catch (error) {
Linha 181: Linha 221:
 
   };
 
   };
  
 +
  /**
 +
  * Aqui usamos nosso GET sem parâmetro para retornar toda a lista
 +
  * de registros
 +
  */
 
   get = async () => {
 
   get = async () => {
 
     try {
 
     try {
Linha 191: Linha 235:
 
   }
 
   }
  
 +
  /**
 +
  * Esse método retorna apenas um objeto (registro). Para isso, precisamos
 +
  * passar como parâmetro o Id do objeto que queremos retornar.
 +
  * Veja que aqui carregamos nos campos texto as informações do json que é
 +
  * retornado e desabilitamos o campo Id para não podermos alterar ele.
 +
  * @param {} id
 +
  */
 
   getUser = async (id) => {
 
   getUser = async (id) => {
 
     try {
 
     try {
Linha 205: Linha 256:
 
   }
 
   }
  
 +
  /**
 +
  * Exclui um registro pelo Id. Depois limpa os estados e dá um
 +
  * refresh na tabela
 +
  * @param {*} id
 +
  */
 
   deleteUser = async (id) => {
 
   deleteUser = async (id) => {
 
     try {
 
     try {
Linha 215: Linha 271:
 
   }
 
   }
  
 +
  /** Apoenas limpa os estados e reabilita o campo Id */
 
   reset = async () => {
 
   reset = async () => {
 
     this.setState({
 
     this.setState({

Edição das 17h44min de 2 de abril de 2024

Afluentes: Usabilidade, Desenvolvimento Web, Mobile e Jogos, Desenvolvimento Front-end II

Serviço web

Para que nosso CRUD possa ser funcional, precisamos de um serviço web com as operações de CRUD (CREATE, READ, UPDATE e DELETE). Para o nosso exemplo aqui, usarei um serviço web desenvolvido em linguagem de programação GO:

Caso você queira reimplementar o serviço em Node.js ou outra linguagem/framework, basta entender o manual de acesso ao serviço web:

Criação do Projeto

Tendo definido o serviço web que iremos consumir, agora vamos para a criação do nosso projeto. Nesse ponto, já temos instalado o npm, node e create-react-app, então vamos criar a pasta do projeto:

$ npx create-react-app reactcrud

Também vamos precisar do Axios, então já vamos instalar ele. Para isso, entre dentro da pasta que do projeto que criamos e baixe o axios:

$ cd reactcrud
$ npm install --save axios

Depois disso, vamos alterar alguns arquivos.

index.css

Para que a tabela fique bonitinha, vamos adicionar um CSS no arquivo index.css

table {
  border-collapse: collapse;
  width: 100%;
}

th,
td {
  text-align: left;
  padding: 8px;
}

tr:nth-child(even) {
  background-color: #ddddff
}

tr:hover {
  background-color: #bbbbff;
}

th {
  background-color: #04AA6D;
  color: white;
}

App.js

E então vamos para o arquivo principal da aplicação

import React, { Component } from 'react';
import axios from 'axios';
import './App.css';

/**
 * Abaixo temos o link do nosso servidor. Como exemplo, coloquei o link
 * de onde coloco minhas APIs para teste no meu servidor online. 
 * 
 * const server = 'https://api.arisa.com.br';
 * 
 * Mas para o desenvolvimenoto estou usando o localhost mesmo. 
 */
const server = 'http://localhost:8080';

class App extends Component {
  /**
   * No constructor inicializamos nossa herança (Component) e
   * instanciamos nossos estados, sendo eles: lista de usuários,
   * id, nome e email referente aos campos de entrada. E o disabled
   * é para desabilitarmos o campo ID quano formos alterar algum
   * registro
   * @param {*} props 
   */
  constructor(props) {
    super(props);
    this.state = {
      users: [],
      user_id: '',
      user_name: '',
      user_email: '',
      disabled: false,
    };
  }

  /** Render é onde criamos a nossa página/aplicação. */
  render() {
    // Linkamos nossos estados localmente na função
    const { users } = this.state;
    const { user_id } = this.state;
    const { user_name } = this.state;
    const { user_email } = this.state;

    return (
      <div>
        <h1>Usuários</h1>
        <form onSubmit={this.handleSubmit}>
          <p>
            <label>ID:
              <input type='text'
                name='user_id'
                value={user_id}
                onChange={this.myChangeHandler}
                disabled={(this.state.disabled) ? "disabled" : ""}
              />
            </label>
          </p>
          <p>
            <label>Name:
              <input type='text'
                name='user_name'
                value={user_name}
                onChange={this.myChangeHandler}
              />
            </label>
          </p>
          <p>
            <label>E-mail:
              <input type='text'
                name='user_email'
                value={user_email}
                onChange={this.myChangeHandler}
              />
            </label>
          </p>
          <p>
            <button>Gravar</button>
            <button type='button' onClick={this.reset}>Limpar</button>
          </p>
        </form>
        <table>
          <thead>
            <tr><th>ID</th><th>Nome</th><th>E-mail</th><th></th></tr>
          </thead>
          <tbody>
            {users.map(user => (
              <tr key={user.id}>
                <td>{user.id}</td>
                <td onClick={() => this.getUser(user.id)}>{user.name}</td>
                <td><a href={"mailto:" + user.email}>{user.email}</a></td>
                <td><button type='button' onClick={() => this.deleteUser(user.id)}>X</button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    );
  }

  /**
   * Esse método é assincrono e é chamado depois que nossa aplicação tiver
   * sido criada. Ele apenas faz chama o método get para carregar os dados
   * da base de dados via serviço web.
   */
  async componentDidMount() {
    this.get();
  }

  /** 
   * Esse evento é chamado sempre que alterarmos alguma informação nos campos
   * de entrada, de forma a atualizar também os estados
   */
  myChangeHandler = (event) => {
    let nam = event.target.name;
    let val = event.target.value;
    this.setState({ [nam]: val });
  }

  /**
   * Quando o botão gravar é clicado, o handleSubmit é chamado para tratar o evento.
   * @param {*} e 
   * @returns 
   */
  handleSubmit = async (e) => {
    // Testamos se o Id pra gravar é válido
    try {
      var id = parseInt(this.state.user_id);
    } catch (error) {
      console.error("Error :", error);
    }
    // vamos garantir que seremos nós que vamos tratar esse evento
    e.preventDefault();
    /* Pegamos nossos dados dos campos de entrada e transformamos em
       uma string JSON */
    const data = JSON.stringify({
      id: id,
      name: this.state.user_name,
      email: this.state.user_email,
    });
    try {
      // Se o campo ID está desabilitado, então é um UPDATE. Usaremos o PUT
      // Caso contrário, será usado o POST. O JSON que criamos, "data" é
      // colocado no corpo da mensagem
      if (this.state.disabled) {
        await axios.put(`${server}/users`, data);
      } else {
        if (this.state.user_id.trim() === "") return;
        await axios.post(`${server}/users`, data);
      }
      // Limpamos os estados
      this.setState({
        user_id: '',
        user_name: '',
        user_email: '',
        disabled: false,
      });
      // Atualizamos a lista da tabela
      this.get();
    } catch (error) {
      console.error("Error creating post:", error);
    }
  };

  /**
   * Aqui usamos nosso GET sem parâmetro para retornar toda a lista
   * de registros
   */
  get = async () => {
    try {
      const response = await axios.get(`${server}/users`, '');
      this.setState({ users: [] });
      this.setState({ users: response.data });
    } catch (error) {
      console.error("Error get users :", error);
    }
  }

  /**
   * Esse método retorna apenas um objeto (registro). Para isso, precisamos
   * passar como parâmetro o Id do objeto que queremos retornar.
   * Veja que aqui carregamos nos campos texto as informações do json que é
   * retornado e desabilitamos o campo Id para não podermos alterar ele.
   * @param {} id 
   */
  getUser = async (id) => {
    try {
      const response = await axios.get(`${server}/users/${id}`);
      this.setState({
        user_id: response.data.id,
        user_name: response.data.name,
        user_email: response.data.email,
        disabled: true,
      });
    } catch (error) {
      console.error("Error get user :", error);
    }
  }

  /**
   * Exclui um registro pelo Id. Depois limpa os estados e dá um
   * refresh na tabela
   * @param {*} id 
   */
  deleteUser = async (id) => {
    try {
      await axios.delete(`${server}/users/${id}`);
      this.reset();
      this.get();
    } catch (error) {
      console.error("Error deleting post:", error);
    }
  }

  /** Apoenas limpa os estados e reabilita o campo Id */
  reset = async () => {
    this.setState({
      user_id: '',
      user_name: '',
      user_email: '',
      disabled: false,
    });
  }
}

export default App;