I am making an job search app with multiple tags to click to filter the job listing using MERN. I am trying to pass multiple query strings to backend and filter the data, but I am not sure how to extract from params and destructure in backend. Currently I made the params into arrays.
Especially when I click two tools like "Vue" and "Sass", it returns ["tool", "Vue"], ["tool", "Sass"],
but I want to combine in backend like {tools: "Vue", "Sass"} to filter easily.
HomeScreen.js
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useSearchParams } from 'react-router-dom';
import Filterbar from '../components/Filterbar';
// import PhotosnapIcon from '~/images/photosnap.svg';
import { listJobs } from '../actions/jobActions';
import './HomeScreen.scss';
export default function HomeScreen() {
const dispatch = useDispatch();
const jobList = useSelector((state) => state.jobList);
const { loading, error, jobs } = jobList;
let [searchParams, setSearchParams] = useSearchParams();
const params = [];
searchParams.forEach((value, key) => {
params.push([key, value]);
}); // this returns ["level", "Junior"], ["language", "JavaScript"], ["tool", "Sass"]
useEffect(() => {
dispatch(listJobs(params));
console.log(jobs);
}, [dispatch]);
const addQuery = (key, value) => {
setSearchParams((prev) => [...prev.entries(), [key, value]]);
};
return (
<>
<Filterbar />
<ul>
{jobs.map((job) => (
<li className={job.featured ? 'post featured' : 'post'} key={job._id}>
<div className="post__img-container">
<img src={job.logo} alt="photosnap" />
</div>
<div className="post__upper-container">
<div className="post__company-container">
<h2 className="post__company">{job.company}</h2>
{job.new && <span className="post__label new">new!</span>}
{job.featured && (
<span className="post__label featured">featured</span>
)}
</div>
<h3 className="post__job-title">{job.position}</h3>
<div className="post__data">
<span className="post__date">{job.postedAt}</span>
<div className="post__dot"></div>
<span className="post__hours">{job.contract}</span>
<div className="post__dot"></div>
<span className="post__location">{job.location}</span>
</div>
</div>
<div className="post__lower-container">
<button
className="post__category"
name="role"
value={job.role}
onClick={(e) => addQuery('role', e.currentTarget.value)}
>
<span>{job.role}</span>
</button>{' '}
<button
className="post__category"
value={job.level}
onClick={(e) => addQuery('level', e.currentTarget.value)}
>
<span>{job.level}</span>
</button>
{job.languages.map((language) => (
<button
className="post__category"
name="language"
value={language}
onClick={(e) => addQuery('language', e.currentTarget.value)}
>
<span>{language}</span>
</button>
))}
{job.tools.map((tool) => (
<button
className="post__category"
name="tool"
value={tool}
onClick={(e) => addQuery('tool', e.currentTarget.value)}
>
<span>{tool}</span>
</button>
))}
</div>
</li>
))}
</ul>
</>
);
}
jobActions.js
import axios from 'axios';
import {
JOB_LIST_REQUEST,
JOB_LIST_SUCCESS,
JOB_LIST_FAIL,
} from '../constants/jobConstants';
export const listJobs =
(params = '') =>
async (dispatch) => {
try {
dispatch({ type: JOB_LIST_REQUEST });
/// NOT SURE about the url
const { data } = await axios.get(`/api/jobs?q=${params}`);
dispatch({
type: JOB_LIST_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: JOB_LIST_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
});
}
};
>backend>controllers>jobs.js : Not sure what to add and how to destructure array to find the listing
import ErrorResponse from '../utils/errorResponse.js';
import asyncHandler from '../middleware/async.js';
import Job from '../models/Job.js';
// @desc Get all jobs
// @routes GET /api/jobs
// @access Public
const getJobs = asyncHandler(async (req, res, next) => {
const jobs = await Job.find({});
res.json(jobs);
});
export { getJobs, getJob, createJob, deleteJob, updateImage, updateJob };
You may want to use URLSearchParams and pass it to axios.get
, since you have key-value pair as an array.
const queryParams = new URLSearchParams(params);
const { data } = await axios.get("/api/jobs", { params: queryParams });
or alternatively you can also send it as object.
const { data } = await axios.get("/api/jobs", {
params: { level: "Junior", language: "JavaScript" },
});