0

Redux newbie here. I'm trying to implement search functionality in my React App. I'm fetching data using the thunk middleware. Here is my slice code:

export const fetchAllJobs = createAsyncThunk(
    'job/fetchJobs',
    async () => {
        const response = await fetch('some-api/availableJobs')
            .then(res => res.json())
        return response;
    }
)
export const jobSlice = createSlice({
    name: 'job',
    initialState: {
        jobs: [],
        searchedJobs: [],
        isLoading: true
    },
    reducers: {
        handleSearchJobs: (state, action) => {
            state.searchedJobs = [];
            state.searchedJobs.push(action.payload)
        },
    },
    extraReducers: (builder) => {
        builder.addCase(fetchAllJobs.fulfilled, (state, action) => {
            state.jobs = action.payload;
            state.searchedJobs = action.payload;
            state.isLoading = false;
        })
        builder.addCase(fetchAllJobs.pending, (state, action) => {
            state.isLoading = true;
        })
    },
});
export const { handleSearchJobs } = jobSlice.actions;
export default jobSlice.reducer;

I am populating the DOM from the fetched data on my Jobs page.

const [jobId, setJobId] = useState('');
// products to be rendered on the UI
const [displayJobs, setDisplayJobs] = useState(useSelector((state) => state.jobs.jobs));
const dispatch = useDispatch();
const jobs = useSelector((state) => state.jobs.jobs);

useEffect(() => {
    dispatch(fetchAllJobs()) 
}, [dispatch, jobs]);

// handle search job 
const handleSearch = event => {
    if (event.target.value) {
        const searchText = event.target.value;
        const matchedJobs = jobs.filter(job => job.jobTitle
        .toLowerCase().includes(searchText.toLowerCase()));
        dispatch(handleSearchJobs(matchedJobs));
    }
}
return (
    <>
        <div className="search-container">
                <TextField
                    sx={{ width: "50%" }}
                    onChange={handleSearch}
                    placeholder="Search Jobs" />
         </div>
         <div className="jobsContainer">
             <div className="jobs-container-left">
                  {
                      displayJobs.map(job => <Job key={job._id}
                              handleSetJob={handleSetJob}
                              job={job}>
                          </Job>)
                    }
              </div>
          </div>
       </>
    );
};

Jobs are loading perfectly fine. But what I want to do is whenever a user types something in the search box, I want to filter jobs that have titles similar to the search text. And then, display only those jobs on the page. I understand there is a filter mechanism that should be implemented on the slice, but after many attempts, I'm just exhausted. Could use some help. TIA.

Tajmin
  • 353
  • 1
  • 7
  • 23

1 Answers1

1

If you have all jobs client-side and just want to search within those, that searching would be done either in a memoized selector (see the computing derived data docs page) or just within a useMemo in your component - I would probably prefer the latter.

const [filter, setFilter] = useState("")
const allJobs = useSelector(state => state.jobs)
const filteredJobs = useMemo(() => allJobs.filter(job => job.startsWith(filter), [filter])

Either way, you would not change your Redux state all the time.

phry
  • 35,762
  • 5
  • 67
  • 81