I'm trying to implement a filter with checkboxes. I have my data in a JSON file. I'm fetching my data from a JSON It looks like:
{
"subjects": [
{
"año_cuatri": "1° 1°",
"codigo": "1.1.1",
"nombre": "Técnicas de Programación",
"estado": "Promocionada",
"año_cursada": "2024 2°C",
"nota": 8,
"tiene_apuntes": true,
"link_apuntes": "111_tecnicas_de_programacion"
},
...
]}
I'm trying to render it, and everything is fine up to there, but when I implement filters with checkboxes, I'm having some troubles. I can't filter the data, and re-render the filtered data. Would you mind helping me? So I've got this:
const Materias_List = () => {
const [dataApi, setDataApi] = useState([]);
const [estadoChecked, setEstadoChecked] = useState({
materia_promocionada: false,
materia_pendiente: false,
materia_cursando: false,
materia_tiene_apuntes: false,
});
let api_subjects = [];
let api_subjects_filtered = [];
const fetchData = async () => {
try {
api_subjects = await degree_in_software_development.subjects;
setDataApi(api_subjects);
} catch (e) {
console.log("Error al consumir API", e);
} finally {
console.log("FINALLY api_subjects", api_subjects);
console.log("FINALLY dataApi", dataApi);
console.log("Finalizó la carga");
}
};
const handleOnChange = async (e) => {
console.log("handleOnChange", e); // e: SyntheticBaseEvent {} > target: input#materia_cursando > checked: true||false
console.log("estadoChecked", estadoChecked);
setEstadoChecked({ ...estadoChecked, [e.target.name]: e.target.checked });
console.log("estadoChecked", estadoChecked);
console.log("e.target.checked", e.target.checked);
console.log("e.target.value", e.target.value);
console.log("e.target.name", e.target.name);
};
useEffect(() => {
fetchData();
console.log("useEffect", api_subjects);
console.log("useEffect dataApi", dataApi);
}, []);
return (
<>
<div>
<p>Filtrar por: </p>
<input
type="checkbox"
id="materia_promocionada"
name="materia_promocionada"
value="Promocionada"
onChange={handleOnChange}
/>
<label htmlFor="materia_promocionada">Promocionada</label>
<input
type="checkbox"
id="materia_pendiente"
name="materia_pendiente"
value="Pendiente"
onChange={handleOnChange}
/>
<label htmlFor="materia_pendiente">Pendiente</label>
<input
type="checkbox"
id="materia_cursando"
name="materia_cursando"
value="Cursando"
onChange={handleOnChange}
/>
<label htmlFor="materia_cursando">Cursando</label>
<input
type="checkbox"
id="materia_tiene_apuntes"
name="materia_tiene_apuntes"
value="tiene_apuntes"
onChange={handleOnChange}
/>
<label htmlFor="materia_tiene_apuntes">Tiene apuntes</label>
</div>
<div id="materias_container">
<ul id="materias_lista">
{dataApi.map((subject) => {
return (
<li key={subject.codigo}>
<div className="materias__item">
<span className={`estado_${subject.estado.toLowerCase()}`}>
{subject.estado}
</span>
<h4>{subject.nombre}</h4>
{!subject.tiene_apuntes ? (
<p className="materias__item-detalle">
<span>Código: {subject.codigo}</span>
</p>
) : subject.tiene_apuntes && subject.link_apuntes ? (
<p className="materias__item-detalle">
<span>Código: {subject.codigo}</span>
<span>
<a
href={`${basePath}${subject.link_apuntes}`}
target="#"
>
📚 Apuntes
</a>
</span>
</p>
) : null}
</div>
</li>
);
})}
</ul>
</div>
</>
);
};
Thanks for your time!
import React, { useEffect, useState } from "react";
const Materias_List = () => {
const [originalData, setOriginalData] = useState([]);
const [dataApi, setDataApi] = useState([]);
const [estadoChecked, setEstadoChecked] = useState({
materia_promocionada: false,
materia_pendiente: false,
materia_cursando: false,
materia_tiene_apuntes: false,
});
const fetchData = async () => {
try {
// Simulated fetch (replace with real fetch if needed)
const response = await fetch("/path/to/your/degree_in_software_development.json");
const json = await response.json();
setOriginalData(json.subjects);
setDataApi(json.subjects);
} catch (e) {
console.error("Error al consumir API", e);
}
};
const handleOnChange = (e) => {
const { name, checked } = e.target;
setEstadoChecked((prev) => ({
...prev,
[name]: checked,
}));
};
useEffect(() => {
fetchData();
}, []);
// Apply filters every time estadoChecked changes
useEffect(() => {
let filtered = [...originalData];
const filters = [];
if (estadoChecked.materia_promocionada) filters.push("Promocionada");
if (estadoChecked.materia_pendiente) filters.push("Pendiente");
if (estadoChecked.materia_cursando) filters.push("Cursando");
// Filter by estado (Promocionada, Pendiente, Cursando)
if (filters.length > 0) {
filtered = filtered.filter((s) => filters.includes(s.estado));
}
// Filter by tiene_apuntes
if (estadoChecked.materia_tiene_apuntes) {
filtered = filtered.filter((s) => s.tiene_apuntes);
}
setDataApi(filtered);
}, [estadoChecked, originalData]);
return (
<>
<div>
<p>Filtrar por: </p>
<label>
<input
type="checkbox"
name="materia_promocionada"
onChange={handleOnChange}
/>
Promocionada
</label>
<label>
<input
type="checkbox"
name="materia_pendiente"
onChange={handleOnChange}
/>
Pendiente
</label>
<label>
<input
type="checkbox"
name="materia_cursando"
onChange={handleOnChange}
/>
Cursando
</label>
<label>
<input
type="checkbox"
name="materia_tiene_apuntes"
onChange={handleOnChange}
/>
Tiene apuntes
</label>
</div>
<div id="materias_container">
<ul id="materias_lista">
{dataApi.map((subject) => (
<li key={subject.codigo}>
<div className="materias__item">
<span className={`estado_${subject.estado.toLowerCase()}`}>
{subject.estado}
</span>
<h4>{subject.nombre}</h4>
<p className="materias__item-detalle">
<span>Código: {subject.codigo}</span>
{subject.tiene_apuntes && subject.link_apuntes && (
<span>
<a href={`/${subject.link_apuntes}`} target="_blank">
📚 Apuntes
</a>
</span>
)}
</p>
</div>
</li>
))}
</ul>
</div>
</>
);
};
export default Materias_List;