This is a React.js
filter problem and I'm stuck here. The problem has static data of movies as an array of objects and we have to filter that data according to the checked state of different checkboxes.
Static Data:
export const data = [
{
id: 1,
title: 'Batman',
rating: 1,
genre: 'Action'
},
{
id: 2,
title: 'Superman',
rating: 5,
genre: 'Comedy'
},
{
id: 3,
title: 'Spiderman',
rating: 3,
genre: 'Thriller'
},
{
id: 4,
title: 'BananaMan',
rating: 2,
genre: 'Action'
},
{
id: 5,
title: 'OrangeMan',
rating: 4,
genre: 'Drama'
}
];
The abstract UI has the following picture that represents 2 types of filters.
- Rating
- Genre
Screenshot:
Both Filters are rendered on the UI as checkboxes. So, I've created a component called Checkboxes
which will take a prop named list
and it is an array of objects.
This list
represents unique ids
of checkboxes which will help us to track the checked
or unchecked
state of the checkbox. The different checkboxes id
will save inside the state which is an array.
const [checkedArray, setCheckedArray] = useState([]);
Finally, I'm rendering this Checkboxes
component twice inside the parent component called App.js
. One for rating and the other for genre.
List:
export const listCheckboxesRating = [
{
id: 0,
name: 'rating',
label: 'Any Rating'
},
{
id: 1,
name: 'rating1',
label: 'Rating 1'
},
{
id: 2,
name: 'rating2',
label: 'Rating 2'
},
{
id: 3,
name: 'rating3',
label: 'Rating 3'
},
{
id: 4,
name: 'rating4',
label: 'Rating 4'
},
{
id: 5,
name: 'rating5',
label: 'Rating 5'
}
];
export const listCheckboxesGenre = [
{
id: 0,
name: 'genre',
label: 'Any Genre'
},
{
id: 1,
name: 'action',
label: 'Action'
},
{
id: 2,
name: 'comedy',
label: 'Comedy'
},
{
id: 3,
name: 'drama',
label: 'Drama'
},
{
id: 4,
name: 'thriller',
label: 'Thriller'
}
];
Checkboxes component:
import {useState} from 'react';
import {handleToggle} from '../../utils';
const Checkboxes = ({list, handleFilters}) => {
const [checkedArray, setCheckedArray] = useState([]);
const onChangeHandler = (checkboxId) => {
const newState = handleToggle(checkboxId, checkedArray);
setCheckedArray(newState);
// Update this checked information into Parent Component
handleFilters(newState);
};
return list.map((item, index) => {
return (
<div key={index}>
<input
type="checkbox"
id={item.name}
checked={checkedArray.indexOf(item.id) !== -1}
onChange={() => onChangeHandler(item.id)}
/>
<label htmlFor={item.name}>{item.label}</label>
</div>
);
});
};
export default Checkboxes;
I'm passing the whole state of these checkboxes through a function named handleFilters
to parent component App.js
. You can see this line of code.
handleFilters(newState);
The App.js
component is saving states of these checkboxes with something like this:
const [selected, setSelected] = useState({
rating: [],
genre: []
});
App.js component:
import {useState} from 'react';
import Checkboxes from './Checkboxes';
import {data, listCheckboxesRating, listCheckboxesGenre} from '../data';
const App = () => {
const [movies, setMovies] = useState(data);
const [selected, setSelected] = useState({
rating: [],
genre: []
});
/**
* This function will perform the filtration process based on the key value.
*
* @param {number[]} checkboxState - It will take the final state of checkboxes
* @param {string} key - It will help us to determine the type of filtration
*/
const handleFilters = (checkboxState, key) => {
const newFilters = {...selected};
newFilters[key] = checkboxState;
// Filtration process
for (let key in newFilters) {
if (
newFilters.hasOwnProperty(key) &&
Array.isArray(newFilters[key]) &&
newFilters[key].length > 0
) {
if (key === 'rating') {
} else if (key === 'genre') {
}
}
}
// Save the filtered movies and update the state.
// setMovies();
setSelected(newFilters);
};
return (
<div>
{movies.map((movie) => (
<div key={movie.id}>
<div>Name: {movie.title}</div>
<div>Genre :{movie.genre}</div>
<div>Rating: {movie.rating}</div>
<hr />
</div>
))}
<div className="row">
<div className="col">
<h1>Filter by Rating</h1>
<Checkboxes
list={listCheckboxesRating}
handleFilters={(checkboxState) =>
handleFilters(checkboxState, 'rating')
}
/>
</div>
<div className="col">
<h1>Filter by Genre</h1>
<Checkboxes
list={listCheckboxesGenre}
handleFilters={(checkboxState) =>
handleFilters(checkboxState, 'genre')
}
/>
</div>
</div>
</div>
);
};
export default App;
The checkboxes checked
or unchecked
state of both filters are working fine and correctly updated with ids
inside the parent selected
state with something like this.
const [selected, setSelected] = useState({
rating: [1,2,3],
genre: [2,4]
});
But here is the confusing part where I'm stuck. How to map these checkboxes ids
and filter the data according to these ids
?
I've defined a function in the App.js
component handleFilters(checkboxState, key)
in which I wanted to iterate the selected
state to perform the filtration process but my mind is not making logic and I need help.
WORKING DEMO:
Aucun commentaire:
Enregistrer un commentaire