refactor: rename variables and create hooks

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe 2024-05-08 08:38:44 +07:00
parent a41b3e565f
commit be494b489c
No known key found for this signature in database
GPG Key ID: CFD53CE570D42DF5
3 changed files with 62 additions and 51 deletions

View File

@ -82,11 +82,11 @@ const constructFilterInput = (filters: {
} }
if (filters[`${PRICE_FILTER_ID}.max`]) { if (filters[`${PRICE_FILTER_ID}.max`]) {
price.max = Number(filters[`${PRICE_FILTER_ID}.max`]); price.max = Number(filters[`${PRICE_FILTER_ID}.max`]);
!price.min && (price.min = 0);
} }
if (price.max && !price.min) { if (price.max || price.min) {
price.min = 0;
}
results.push({ price }); results.push({ price });
}
return results; return results;
}; };

View File

@ -1,6 +1,7 @@
'use client'; 'use client';
import Price from 'components/price'; import Price from 'components/price';
import { useDebounce } from 'hooks';
import { Filter } from 'lib/shopify/types'; import { Filter } from 'lib/shopify/types';
import { createUrl } from 'lib/utils'; import { createUrl } from 'lib/utils';
import get from 'lodash.get'; import get from 'lodash.get';
@ -16,21 +17,6 @@ const currencySymbol =
.formatToParts(1) .formatToParts(1)
.find((part) => part.type === 'currency')?.value || '$'; .find((part) => part.type === 'currency')?.value || '$';
const useDebounce = (value: string, delay = 500) => {
const [debouncedValue, setDebouncedValue] = useState('');
const timerRef = useRef<ReturnType<typeof setTimeout>>();
useEffect(() => {
timerRef.current = setTimeout(() => setDebouncedValue(value), delay);
return () => {
clearTimeout(timerRef.current);
};
}, [value, delay]);
return debouncedValue;
};
const PriceRange = ({ id, values }: { id: string; values: Filter['values'] }) => { const PriceRange = ({ id, values }: { id: string; values: Filter['values'] }) => {
const highestPrice = values.reduce( const highestPrice = values.reduce(
(acc, { value }) => Math.max(acc, get(value, 'price.max', 0)), (acc, { value }) => Math.max(acc, get(value, 'price.max', 0)),
@ -41,76 +27,85 @@ const PriceRange = ({ id, values }: { id: string; values: Filter['values'] }) =>
const pathname = usePathname(); const pathname = usePathname();
const router = useRouter(); const router = useRouter();
const priceMin = searchParams.get(`${id}.min`); const initialPriceMin = searchParams.get(`${id}.min`);
const priceMax = searchParams.get(`${id}.max`); const initialPriceMax = searchParams.get(`${id}.max`);
const [min, setMin] = useState(priceMin || ''); const [minPrice, setMinPrice] = useState(initialPriceMin || '');
const [max, setMax] = useState(priceMax || ''); const [maxPrice, setMaxPrice] = useState(initialPriceMax || '');
const debouncedMin = useDebounce(min); const debouncedMinPrice = useDebounce(minPrice);
const debouncedMax = useDebounce(max); const debouncedMaxPrice = useDebounce(maxPrice);
const minRef = useRef(min); const minPriceRef = useRef(minPrice);
const maxRef = useRef(max); const maxPriceRef = useRef(maxPrice);
const updateSearchParams = useCallback( const updateSearchParams = useCallback(
(priceRange: { min: string; max: string }) => { (priceRange: { min: string; max: string }) => {
const newSearchParams = new URLSearchParams(searchParams); const newSearchParams = new URLSearchParams(searchParams);
if (!priceRange.min) {
newSearchParams.delete(`${id}.min`);
} else {
newSearchParams.set(`${id}.min`, priceRange.min); newSearchParams.set(`${id}.min`, priceRange.min);
}
if (!priceRange.max) {
newSearchParams.delete(`${id}.max`);
} else {
newSearchParams.set(`${id}.max`, priceRange.max); newSearchParams.set(`${id}.max`, priceRange.max);
}
router.replace(createUrl(pathname, newSearchParams), { scroll: false }); router.replace(createUrl(pathname, newSearchParams), { scroll: false });
}, },
[id, pathname, router, searchParams] [id, pathname, router, searchParams]
); );
const handleChangeMinPrice = (value: string) => { const handleChangeMinPrice = (value: string) => {
setMin(value); setMinPrice(value);
minRef.current = value; minPriceRef.current = value;
}; };
const handleChangeMaxPrice = (value: string) => { const handleChangeMaxPrice = (value: string) => {
setMax(value); setMaxPrice(value);
maxRef.current = value; maxPriceRef.current = value;
}; };
useEffect(() => { useEffect(() => {
if (debouncedMin) { if (debouncedMinPrice) {
let _minPrice = debouncedMin; let _minPrice = debouncedMinPrice;
const minNum = Number(_minPrice); const minNum = Number(_minPrice);
if (minNum < 0) { if (minNum < 0) {
_minPrice = '0'; _minPrice = '0';
} }
if (maxRef.current && minNum > Number(maxRef.current)) { if (maxPriceRef.current && minNum > Number(maxPriceRef.current)) {
_minPrice = maxRef.current; _minPrice = maxPriceRef.current;
} }
if (minNum > highestPrice) { if (minNum > highestPrice) {
_minPrice = String(highestPrice); _minPrice = String(highestPrice);
} }
if (_minPrice !== debouncedMin) { if (_minPrice !== debouncedMinPrice) {
handleChangeMinPrice(_minPrice); handleChangeMinPrice(_minPrice);
} }
updateSearchParams({ min: _minPrice, max: maxRef.current }); updateSearchParams({ min: _minPrice, max: maxPriceRef.current });
} else { } else {
updateSearchParams({ min: '', max: maxRef.current }); updateSearchParams({ min: '', max: maxPriceRef.current });
} }
}, [debouncedMin, highestPrice, updateSearchParams]); }, [debouncedMinPrice, highestPrice, updateSearchParams]);
useEffect(() => { useEffect(() => {
if (debouncedMax) { if (debouncedMaxPrice) {
let _maxPrice = debouncedMax; let _maxPrice = debouncedMaxPrice;
const maxNum = Number(_maxPrice); const maxNum = Number(_maxPrice);
if (minRef.current && maxNum < Number(minRef.current)) { if (minPriceRef.current && maxNum < Number(minPriceRef.current)) {
_maxPrice = minRef.current; _maxPrice = minPriceRef.current;
} }
if (maxNum > highestPrice) { if (maxNum > highestPrice) {
_maxPrice = String(highestPrice); _maxPrice = String(highestPrice);
} }
if (_maxPrice !== debouncedMax) { if (_maxPrice !== debouncedMaxPrice) {
handleChangeMaxPrice(_maxPrice); handleChangeMaxPrice(_maxPrice);
} }
updateSearchParams({ min: minRef.current, max: _maxPrice }); updateSearchParams({ min: minPriceRef.current, max: _maxPrice });
} else { } else {
updateSearchParams({ min: minRef.current, max: '' }); updateSearchParams({ min: minPriceRef.current, max: '' });
} }
}, [debouncedMax, highestPrice, updateSearchParams]); }, [debouncedMaxPrice, highestPrice, updateSearchParams]);
return ( return (
<div className="flex flex-col"> <div className="flex flex-col">
@ -126,7 +121,7 @@ const PriceRange = ({ id, values }: { id: string; values: Filter['values'] }) =>
min={0} min={0}
max={highestPrice} max={highestPrice}
placeholder="From" placeholder="From"
value={min} value={minPrice}
onChange={(e) => handleChangeMinPrice(e.target.value)} onChange={(e) => handleChangeMinPrice(e.target.value)}
/> />
</div> </div>
@ -135,10 +130,10 @@ const PriceRange = ({ id, values }: { id: string; values: Filter['values'] }) =>
<input <input
className="w-28 rounded border-none text-sm focus:ring-0 focus:ring-offset-0" className="w-28 rounded border-none text-sm focus:ring-0 focus:ring-offset-0"
type="number" type="number"
min={min} min={minPrice}
max={highestPrice} max={highestPrice}
placeholder="To" placeholder="To"
value={max} value={maxPrice}
onChange={(e) => handleChangeMaxPrice(e.target.value)} onChange={(e) => handleChangeMaxPrice(e.target.value)}
/> />
</div> </div>

16
hooks/index.tsx Normal file
View File

@ -0,0 +1,16 @@
import { useEffect, useRef, useState } from 'react';
export const useDebounce = (value: string, delay = 500) => {
const [debouncedValue, setDebouncedValue] = useState('');
const timerRef = useRef<ReturnType<typeof setTimeout>>();
useEffect(() => {
timerRef.current = setTimeout(() => setDebouncedValue(value), delay);
return () => {
clearTimeout(timerRef.current);
};
}, [value, delay]);
return debouncedValue;
};