I have a brand filter toggle that when it is triggered it adds or deletes a element to a brand's array and then in my context when i detect that the brand's array changed i make a second api call to add the brand filters to my api call.
And the moment when i update my state for the first time it works perfectly, the array updates and adds a new brand to the stack, but when i add a second one while looking at the components tab in developer's mode the state doesn't update but when i close developers tool's and open them again it appears as the delete or aggregation to the state worked, but the useEffect isn't triggered.
Working state when i click on the checkbox for the first time:
Not working at first when i update for the second time:
State updates when i close and open developers tools, but the useEffect isn't triggered adding a new parameter to the url:
If i check and then uncheck one box it updates correctly.
I don't really know why is this happening, if it's the context's state not updating properly or my component state not updating properly, it might be the component state not working but it is really weird that it updates after closing and opening and when i console log it it appears as updated.
Here is my sidebar component:
import "../App.css";
import React, { useContext } from "react";
import { ProductContext } from "../context/productContext";
const Sidebar = () => {
const { products, setProducts, brandFilter, setBrandFilter } =
useContext(ProductContext);
var brandsArray = [];
brandsArray.push(products[0].company);
for (var i = 1; i < products.length; i++) {
var isEqual = false;
for (var x = 0; x < brandsArray.length; x++) {
if (products[i].company == brandsArray[x]) {
isEqual = true;
}
}
if (isEqual == false) {
brandsArray.push(products[i].company);
}
}
const handleClick = (e) => {
var arrayFilters = [];
var isEqual = -1;
if (brandFilter.length > 0) {
arrayFilters = brandFilter;
}
for (var i = 0; i < arrayFilters.length; i++) {
if (e.target.value == arrayFilters[i]) {
isEqual = i;
}
}
if (isEqual == -1) {
arrayFilters.push(e.target.value);
} else {
arrayFilters.splice(isEqual, 1);
}
setBrandFilter(arrayFilters);
};
return (
<div className="sidebar p-2">
<div className="heading d-flex justify-content-between align-items-center">
<h6 className="text-uppercase">Brands</h6>
</div>
{brandsArray.map((brand) => (
<div className="d-flex justify-content-between mt-2">
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
value={brand}
id="flexCheckDefault"
onClick={handleClick}
></input>
<label className="form-check-label"> {brand} </label>
</div>
</div>
))}
</div>
);
};
export default Sidebar;
And here is the context:
import React, { useState, createContext, useEffect } from "react";
export const ProductContext = createContext();
export const ProductProvider = (props) => {
var url = "/api/v1/products?";
const [productList, setProductList] = useState([]);
const [products, setProducts] = useState([]);
const [brandFilter, setBrandFilter] = useState([]);
const getProductList = async () => {
const response = await fetch(url);
const responseJson = await response.json();
if (responseJson) {
setProductList(responseJson.products);
}
};
const getProducts = async () => {
const response = await fetch("/api/v1/products?all=true");
const responseJson = await response.json();
if (responseJson) {
setProducts(responseJson.products);
}
};
useEffect(() => {
getProductList();
getProducts();
}, []);
useEffect(() => {
console.log("Something changed");
changeUrl();
getProductList();
}, [brandFilter]);
const changeUrl = () => {
if (brandFilter.length > 0) {
for (var i = 0; i < brandFilter.length; i++) {
url += `company=${brandFilter[i]}&`;
}
}
};
return (
<ProductContext.Provider
value={{
productList,
setProductList,
products,
setProducts,
brandFilter,
setBrandFilter,
}}
>
{props.children}
</ProductContext.Provider>
);
};
export default ProductProvider;