From de45775b0920321e3c2f3ac6604717ed9b532268 Mon Sep 17 00:00:00 2001 From: Jhon Vente Date: Tue, 20 Feb 2024 09:28:42 -0500 Subject: [PATCH] feat: usedebounce hook for searching courses --- src/hooks.js | 25 +++++++++++- .../courses-tab/courses-filters/index.jsx | 39 ++++++++++++------- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/hooks.js b/src/hooks.js index 8c649ea06b..c162608243 100644 --- a/src/hooks.js +++ b/src/hooks.js @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { history } from '@edx/frontend-platform'; // eslint-disable-next-line import/prefer-default-export @@ -32,3 +32,26 @@ export const useEscapeClick = ({ onEscape, dependency }) => { }; }, [dependency]); }; + +/** + * Custom hook to debounce a string value. + * + * @param {string} value - The string value to be debounced. + * @param {number} [delay=500] - The delay in milliseconds before updating the debounced value. + * @returns {string} The debounced string value. + */ +export const useDebounce = (value, delay = 500) => { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const timer = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + return () => { + clearTimeout(timer); + }; + }, [value, delay]); + + return debouncedValue; +}; diff --git a/src/studio-home/tabs-section/courses-tab/courses-filters/index.jsx b/src/studio-home/tabs-section/courses-tab/courses-filters/index.jsx index 94c30ed230..c3989fc1b3 100644 --- a/src/studio-home/tabs-section/courses-tab/courses-filters/index.jsx +++ b/src/studio-home/tabs-section/courses-tab/courses-filters/index.jsx @@ -1,8 +1,10 @@ +import { useState, useEffect } from 'react'; import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import { SearchField } from '@openedx/paragon'; import { getStudioHomeCoursesParams } from '../../../data/selectors'; import { updateStudioHomeCoursesCustomParams } from '../../../data/slice'; +import { useDebounce } from '../../../../hooks'; import CoursesTypesFilterMenu from './courses-types-filter-menu'; import CoursesOrderFilterMenu from './courses-order-filter-menu'; @@ -14,21 +16,10 @@ const CoursesFilters = ({ dispatch }) => { activeOnly, archivedOnly, } = useSelector(getStudioHomeCoursesParams); + const [inputSearchValue, setInputSearchValue] = useState(''); + const searchValueDebounced = useDebounce(inputSearchValue); - const handleSearchCourses = (value) => { - const isSearchEmpty = !value.trim().length; - - const params = { - page: isSearchEmpty ? 1 : currentPage, - search: isSearchEmpty ? undefined : value, - activeOnly, - archivedOnly, - order, - isFiltered: true, - }; - - dispatch(updateStudioHomeCoursesCustomParams(params)); - }; + const handleSearchCourses = (value) => setInputSearchValue(value); const getFilterTypeData = (baseFilters) => ({ archivedCourses: { ...baseFilters, archivedOnly: true }, @@ -53,6 +44,26 @@ const CoursesFilters = ({ dispatch }) => { dispatch(updateStudioHomeCoursesCustomParams(filterParamsFormat)); }; + useEffect(() => { + const loadCoursesSearched = () => { + const valueFormatted = searchValueDebounced.trim(); + const isSearchEmpty = !valueFormatted.length; + + const params = { + page: isSearchEmpty ? 1 : currentPage, + search: isSearchEmpty ? undefined : valueFormatted, + activeOnly, + archivedOnly, + order, + isFiltered: true, + }; + + dispatch(updateStudioHomeCoursesCustomParams(params)); + }; + + loadCoursesSearched(); + }, [searchValueDebounced]); + return (