I am using react to create some page that requires a filtering menu. I have a dogs array which contain every dog information, and I am trying to filtering by its temperaments. every dog has at least three temperaments, and I have been trying to check if they have at least one of the temperaments submitted in the filter menu. But nothing seems to work.
This the controling component.
import {useEffect, useState} from "react";
import {useDispatch, useSelector} from "react-redux";
import {filteringDogs, getTemps, onSearchBreed, orderAscendingDogs, orderDescendingDogs} from "../store";
import styles from "./styles/SideBarComp.module.css";
import {useForm} from "../hooks";
export const SideBarComp = () => {
const dispatch = useDispatch()
const { dogs } = useSelector( state => state.dogs )
const { temps } = useSelector( state => state.temps )
useEffect(() => {
dispatch(getTemps())
}, [])
const { breed, onInputChange } = useForm({
breed: '',
})
const [selectedTemperaments, setSelectedTemperaments] = useState([]);
const handleTempCheckboxChange = (tempName) => {
// Update the selectedTemperaments array based on checkbox changes
if (selectedTemperaments.includes(tempName)) {
setSelectedTemperaments(
selectedTemperaments.filter((temp) => temp !== tempName)
);
} else {
setSelectedTemperaments([tempName, ...selectedTemperaments]);
}
dispatch(filteringDogs(selectedTemperaments))
};
// console.log(selectedTemperaments);
const onSubmit = (event) => {
event.preventDefault()
dispatch(onSearchBreed({ breed }));
}
const onAscendingClick = (dogs) => {
dispatch(orderAscendingDogs(dogs));
};
const onDescendingClick = (dogs) => {
dispatch(orderDescendingDogs(dogs));
};
return (
<main className={styles.sideBar}>
<form onSubmit={onSubmit} className={styles.searchSection}>
<input
className={styles.searchBar}
type="text"
placeholder="Golden retriever..."
name="breed"
value={breed}
onChange={onInputChange}
/>
<button type="submit" className={styles.searchButton}>
Search
</button>
<section className={styles.filterSection}>
<div className={styles.tempFilter}>
<h3>Filter by temperaments</h3>
<div className={styles.inputs}>
{temps.map((item) => (
<div key={item.id} className={styles.singleInput}>
<input
id={item.name}
name={item.name}
type="checkbox"
onChange={() => handleTempCheckboxChange(item.name)}
/>
<label htmlFor={item.name}>{item.name}</label>
</div>
))}
</div>
</div>
</section>
</form>
<div className={styles.orderFilter}>
<h3>Order</h3>
<div className={styles.orderButtonsArea}>
<button
onClick={() => onAscendingClick(dogs)}
className={styles.orderButtons}
>
A - Z
</button>
<button
onClick={() => onDescendingClick(dogs)}
className={styles.orderButtons}
>
Z - A
</button>
</div>
</div>
</main>
);
};
Here it is my store and reducer
import { createSlice } from "@reduxjs/toolkit";
export const dogSlice = createSlice({
name: "dogs",
initialState: {
dogs: [],
loading: false,
currentPage: 1,
itemsPerPage: 8,
totalPages: 0,
},
reducers: {
startLoading: (state /* action */) => {
state.loading = true;
},
setDogs: (state, action) => {
state.dogs = action.payload;
state.totalPages = Math.ceil(action.payload.length / 8);
state.loading = false;
},
setCurrentPage: (state, action) => {
state.currentPage = action.payload;
},
findbyDogBreed: (state, action) => {
state.dogs = action.payload;
state.loading = false;
},
},
});
// Action creators are generated for each case reducer function
export const {
startLoading,
setDogs,
setCurrentPage,
descendingOrder,
ascendingOrder,
findbyDogBreed,
} = dogSlice.actions;
import { setCurrentPage, setDogs, startLoading } from "./dogSlice";
import { dogIns } from "../../../api";
export const getDogs = (page = 1) => {
return async (dispatch) => {
dispatch(startLoading());
const { data } = await dogIns.get("/dogs");
dispatch(setDogs(data));
dispatch(setCurrentPage(page));
};
};
export const handlePages = (page = 1) => {
return async (dispatch) => {
dispatch(setCurrentPage(page));
};
};
export const orderDescendingDogs = (dogs) => {
return async (dispatch) => {
dispatch(startLoading());
const dogsSorted = [...dogs].sort((a, b) => {
const nameA = a.name;
const nameB = b.name;
if (nameA > nameB) {
return -1;
}
if (nameA < nameB) {
return 1;
}
return 0;
});
dispatch(setDogs(dogsSorted));
};
};
export const orderAscendingDogs = (dogs) => {
return async (dispatch) => {
dispatch(startLoading());
const dogsSorted = [...dogs].sort((a, b) => {
const nameA = a.name;
const nameB = b.name;
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
});
dispatch(setDogs(dogsSorted));
};
};
export const onSearchBreed = ({ breed }) => {
return async (dispatch) => {
const { data } = await dogIns.get("/dogs");
const dogsMatching = data.filter((item) =>
item.name.toLowerCase().startsWith(breed.toLowerCase())
);
dispatch(setDogs(dogsMatching));
};
};
export const filteringDogs = (selectedTemperaments) => {
return async (dispatch) => {
// console.log(selectedTemperaments);
const { data } = await dogIns.get("/dogs");
const dogsMatching = data.filter((dog) =>
selectedTemperaments.some((temp) => dog.temperaments.includes(temp))
);
dispatch(setDogs(dogsMatching));
};
};
I already tried a for loop, maybe I didn't use it well, but didn't work. I have been using AI but the options haven't work either, and I just found options on youtube for filtering a single property at the time.
Via Active questions tagged javascript - Stack Overflow https://ift.tt/kdCn58I
Comments
Post a Comment