Para completar el siguiente ejercicio, vamos a replicar lo que ya habíamos hecho en una publicación pasada: https://fernando-gaitan.com.ar/javascript-parte-13-ajax/ Pero con código de React.
Vamos a crear dos componentes: PostsList.jsx y PostItem.jsx.
El componente PostsList.jsx tendrá el siguiente código:
export const PostsList = () => {
return (
<form>
<h1>Ejemplo de API</h1>
<select className="form-select mb-3">
<option value=""> Mostrar todo </option>
<option value="completas"> Mostrar completas </option>
<option value="incompletas"> Mostrar incompletas </option>
</select>
<button type="button" className="btn btn-primary mb-3"> Mostrar lista de tareas </button>
<ul className="list-group">
</ul>
</form>
)
}
Lo agregamos al componente principal main.jsx:
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import 'bootstrap/dist/css/bootstrap.min.css'
import { PostsList } from './components/PostsList'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<div className='container mt-3'>
<PostsList />
</div>
</React.StrictMode>,
)
Analizamos el funcionamiento de PostsList.jsx: lo que queremos hacer, es que al presionar el botón «Mostrar lista de tareas» nos muestre un resultado dependiendo de lo seleccionado en el combo:
<select className="form-select mb-3">
<option value=""> Mostrar todo </option>
<option value="completas"> Mostrar completas </option>
<option value="incompletas"> Mostrar incompletas </option>
</select>
Para ello vamos a necesitar de dos estados: uno para guardar la opción seleccionada del combo (el filtro) y otro para guardar la información que nos devuelva el API
Importamos el hook useState:
import { useState } from "react"
Los estados:
//Opciones del combo.
const [filtro, setFiltro] = useState("");
//La información que me devolverá el API.
const [lista, setLista] = useState([]);
Vamos a modificar el combo de la siguiente forma:
<select className="form-select mb-3" value={filtro} onChange={e => setFiltro(e.target.value)}>
<option value=""> Mostrar todo </option>
<option value="completas"> Mostrar completas </option>
<option value="incompletas"> Mostrar incompletas </option>
</select>
Y a agregar la función que va a llamar al API:
const mostrarTareas = async () => {
let url = 'https://jsonplaceholder.typicode.com/todos';
if(filtro == "completas"){
url += '?completed=true';
}else if(filtro == "incompletas"){
url += '?completed=false';
}
try{
let request = await fetch(url);
let response = await request.json();
console.log(response);
setLista(response);
}catch(e){
alert("Error al intentar recuperar las tareas");
}
}
Agregamos el evento onClick al botón:
<button onClick={mostrarTareas} type="button" className="btn btn-primary mb-3"> Mostrar lista de tareas </button>
Por último vamos a editar el componente PostItem.jsx para poder representar cada uno de los POST que devuelve el API:
export const PostItem = ( {title, completed} ) => {
const getClass = () => {
return (completed) ? "list-group-item list-group-item-success" : "list-group-item list-group-item-danger";
}
return (
<li className={getClass()}>
{title}
</li>
)
}
Finalmente el código PostsList.jsx quedará así:
import { useState } from "react"
import { PostItem } from "./PostItem";
export const PostsList = () => {
//Opciones del combo.
const [filtro, setFiltro] = useState("");
//La información que me devolverá el API.
const [lista, setLista] = useState([]);
const mostrarTareas = async () => {
let url = 'https://jsonplaceholder.typicode.com/todos';
if(filtro == "completas"){
url += '?completed=true';
}else if(filtro == "incompletas"){
url += '?completed=false';
}
try{
let request = await fetch(url);
let response = await request.json();
console.log(response);
setLista(response);
}catch(e){
alert("Error al intentar recuperar las tareas");
}
}
return (
<form>
<h1>Ejemplo de listas</h1>
<select className="form-select mb-3" value={filtro} onChange={e => setFiltro(e.target.value)}>
<option value=""> Mostrar todo </option>
<option value="completas"> Mostrar completas </option>
<option value="incompletas"> Mostrar incompletas </option>
</select>
<button onClick={mostrarTareas} type="button" className="btn btn-primary mb-3"> Mostrar lista de tareas </button>
<ul className="list-group">
{
lista.map((item) => (
<PostItem key={item.id} title={item.title} completed={item.completed} />
))
}
</ul>
</form>
)
}
useEffect
Es un hook que se carga al igual que useState:
import { useEffect, useState } from "react"
Sirve para ejecutar código una vez que se crea el componente.
Recibe dos argumentos: La función que se ejecuta y las dependencias. Si alguna de estas última se modifica se volverá a ejecutar el código que se pasa en el primer argumento:
useEffect(() => {
mostrarTareas();
}, [])
Al inicio se llamará a la función mostrarTareas().
Podríamos agregarle como dependencia el filtro, y esto hará que cada vez que cambie el valor de éste, se ejecutará nuevamente el código sin necesidad de que pulsemos en el botón:
useEffect(() => {
mostrarTareas();
}, [filtro])