How would I go about filtering results from an API using the dropdown?
I currently have a select tag like so
<select value={selectMonthFilter} onChange={e=> setSelectMonthFilter(e.currentTarget.value)}> {console.log(selectMonthFilter)} <option value="">---</option> <option value="">Jan</option> <option value="">Feb</option> <option value="">Mar</option> ... </select>
The list is also displaying all the results from the API with
const [data, setData] = useState([]); const [selectMonthFilter, setSelectMonthFilter] = useState(data)
Example of what the API returns
{ "id": 1, "first_name": "Bob", "last_name": "Smith", "birthdate": "1970-04-19T08:56:27Z", },
Where 1970 is the year, 04 is the month, 19 is the day and the string after is time.
How would I implement so if the user selects Mar on the dropdown, it filters all the people that have their birthdays in March?
I tried testing the following but it doesn’t seem to select anything
const selectMonths = (selectMonthFilter) => { setSelectMonthFilter(selectMonthFilter) console.log(selectMonthFilter) }; <select value={selectMonthFilter} onChange={event => selectMonths(event.target.value)} >
https://codesandbox.io/s/api-test-c4swl?file=/src/pages/home.jsx
Advertisement
Answer
Provide month option values that match the month portion of the birthdate dateTime string.
<label> Select Month <select value={selectMonthFilter} onChange={(e) => setSelectMonthFilter(e.currentTarget.value)} > <option value="">---</option> <option value="01">Jan</option> <option value="02">Feb</option> <option value="03">Mar</option> <option value="04">Apr</option> <option value="05">May</option> <option value="06">Jun</option> <option value="07">Jul</option> <option value="08">Aug</option> <option value="09">Sep</option> <option value="10">Oct</option> <option value="11">Nov</option> <option value="12">Dec</option> </select> </label>
You can split the birthdate by “T” to get the date prefix, then split that by “-” and take the month part.
const getMonthValue = (dateTime) => dateTime.toLowerCase().split("t")[0].split("-")[1];
Once you’ve the month value you can filter your data by birthdates that match the selected month value. If there is no month to filter by then return true to include all data.
{data .filter(({ birthdate }) => selectMonthFilter ? getMonthValue(birthdate) === selectMonthFilter : true ) .map((el) => ( // map your JSX here ))}
If you have more filters you can combine them in the single .filter
callback.
Example:
{data .filter(({ birthdate, first_name, last_name, preferred_name }) => selectMonthFilter || searchNameFilter ? (selectMonthFilter && getMonthValue(birthdate) === selectMonthFilter) || (searchNameFilter && [first_name, last_name, preferred_name] .join(" ") .toLowerCase() .includes(searchNameFilter)) : true ) .map((el) => ( ... ))}
It’s up to you to decide if all the conditions need to be met (logical AND all conditions), or if any of them can match (logical OR all conditions).