Fix price slider constraints (https://github.com/woocommerce/woocommerce-blocks/pull/1125)
* Fix price slider constraints * Update inline comments * use previous tests
This commit is contained in:
parent
0295379b49
commit
c824b481e2
|
@ -12,7 +12,7 @@ import {
|
||||||
} from '@wordpress/element';
|
} from '@wordpress/element';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { useDebounce } from '@woocommerce/base-hooks';
|
import { useDebounce, usePrevious } from '@woocommerce/base-hooks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -47,15 +47,25 @@ const PriceSlider = ( {
|
||||||
formatCurrencyForInput( maxPrice, priceFormat, currencySymbol )
|
formatCurrencyForInput( maxPrice, priceFormat, currencySymbol )
|
||||||
);
|
);
|
||||||
const debouncedChangeValue = useDebounce( [ minPrice, maxPrice ], 500 );
|
const debouncedChangeValue = useDebounce( [ minPrice, maxPrice ], 500 );
|
||||||
|
const prevMinConstraint = usePrevious( minConstraint );
|
||||||
|
const prevMaxConstraint = usePrevious( maxConstraint );
|
||||||
|
|
||||||
useEffect( () => {
|
useEffect( () => {
|
||||||
if ( minPrice === undefined || minConstraint > minPrice ) {
|
if (
|
||||||
|
minPrice === undefined ||
|
||||||
|
minConstraint > minPrice ||
|
||||||
|
minPrice === prevMinConstraint
|
||||||
|
) {
|
||||||
setMinPrice( minConstraint );
|
setMinPrice( minConstraint );
|
||||||
}
|
}
|
||||||
}, [ minConstraint ] );
|
}, [ minConstraint ] );
|
||||||
|
|
||||||
useEffect( () => {
|
useEffect( () => {
|
||||||
if ( maxPrice === undefined || maxConstraint < maxPrice ) {
|
if (
|
||||||
|
maxPrice === undefined ||
|
||||||
|
maxConstraint < maxPrice ||
|
||||||
|
maxPrice === prevMaxConstraint
|
||||||
|
) {
|
||||||
setMaxPrice( maxConstraint );
|
setMaxPrice( maxConstraint );
|
||||||
}
|
}
|
||||||
}, [ maxConstraint ] );
|
}, [ maxConstraint ] );
|
||||||
|
@ -82,6 +92,18 @@ const PriceSlider = ( {
|
||||||
* Handles styles for the shaded area of the range slider.
|
* Handles styles for the shaded area of the range slider.
|
||||||
*/
|
*/
|
||||||
const getProgressStyle = useMemo( () => {
|
const getProgressStyle = useMemo( () => {
|
||||||
|
if (
|
||||||
|
! isFinite( minPrice ) ||
|
||||||
|
! isFinite( maxPrice ) ||
|
||||||
|
! isFinite( minConstraint ) ||
|
||||||
|
! isFinite( maxConstraint )
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
'--low': '0%',
|
||||||
|
'--high': '100%',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const low =
|
const low =
|
||||||
Math.round(
|
Math.round(
|
||||||
100 *
|
100 *
|
||||||
|
@ -99,7 +121,7 @@ const PriceSlider = ( {
|
||||||
'--low': low + '%',
|
'--low': low + '%',
|
||||||
'--high': high + '%',
|
'--high': high + '%',
|
||||||
};
|
};
|
||||||
}, [ minPrice, minConstraint, maxPrice, maxConstraint ] );
|
}, [ minPrice, maxPrice, minConstraint, maxConstraint ] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger the onChange prop callback with new values.
|
* Trigger the onChange prop callback with new values.
|
||||||
|
|
|
@ -4,3 +4,4 @@ export * from './use-store-products';
|
||||||
export * from './use-collection';
|
export * from './use-collection';
|
||||||
export * from './use-collection-header';
|
export * from './use-collection-header';
|
||||||
export * from './use-debounce';
|
export * from './use-debounce';
|
||||||
|
export * from './use-previous';
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import TestRenderer, { act } from 'react-test-renderer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { usePrevious } from '../use-previous';
|
||||||
|
|
||||||
|
describe( 'usePrevious', () => {
|
||||||
|
const TestComponent = ( { testValue } ) => {
|
||||||
|
const previousValue = usePrevious( testValue );
|
||||||
|
return <div testValue={ testValue } previousValue={ previousValue } />;
|
||||||
|
};
|
||||||
|
|
||||||
|
let renderer;
|
||||||
|
beforeEach( () => ( renderer = null ) );
|
||||||
|
|
||||||
|
it( 'should be undefined at first pass', () => {
|
||||||
|
act( () => {
|
||||||
|
renderer = TestRenderer.create( <TestComponent testValue={ 1 } /> );
|
||||||
|
} );
|
||||||
|
const testValue = renderer.root.findByType( 'div' ).props.testValue;
|
||||||
|
const testPreviousValue = renderer.root.findByType( 'div' ).props
|
||||||
|
.previousValue;
|
||||||
|
|
||||||
|
expect( testValue ).toBe( 1 );
|
||||||
|
expect( testPreviousValue ).toBe( undefined );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'test new and previous value', () => {
|
||||||
|
let testValue;
|
||||||
|
let testPreviousValue;
|
||||||
|
act( () => {
|
||||||
|
renderer = TestRenderer.create( <TestComponent testValue={ 1 } /> );
|
||||||
|
} );
|
||||||
|
|
||||||
|
act( () => {
|
||||||
|
renderer.update( <TestComponent testValue={ 2 } /> );
|
||||||
|
} );
|
||||||
|
testValue = renderer.root.findByType( 'div' ).props.testValue;
|
||||||
|
testPreviousValue = renderer.root.findByType( 'div' ).props
|
||||||
|
.previousValue;
|
||||||
|
expect( testValue ).toBe( 2 );
|
||||||
|
expect( testPreviousValue ).toBe( 1 );
|
||||||
|
|
||||||
|
act( () => {
|
||||||
|
renderer.update( <TestComponent testValue={ 3 } /> );
|
||||||
|
} );
|
||||||
|
testValue = renderer.root.findByType( 'div' ).props.testValue;
|
||||||
|
testPreviousValue = renderer.root.findByType( 'div' ).props
|
||||||
|
.previousValue;
|
||||||
|
expect( testValue ).toBe( 3 );
|
||||||
|
expect( testPreviousValue ).toBe( 2 );
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { useRef, useEffect } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use Previous from https://usehooks.com/usePrevious/.
|
||||||
|
* @param {mixed} value
|
||||||
|
*/
|
||||||
|
export const usePrevious = ( value ) => {
|
||||||
|
const ref = useRef();
|
||||||
|
|
||||||
|
useEffect( () => {
|
||||||
|
ref.current = value;
|
||||||
|
}, [ value ] );
|
||||||
|
|
||||||
|
return ref.current;
|
||||||
|
};
|
|
@ -45,10 +45,12 @@ const PriceFilterBlock = ( { attributes } ) => {
|
||||||
const { showInputFields, showFilterButton } = attributes;
|
const { showInputFields, showFilterButton } = attributes;
|
||||||
const minConstraint = isLoading
|
const minConstraint = isLoading
|
||||||
? undefined
|
? undefined
|
||||||
: parseInt( results.min_price, 10 );
|
: // Round up to nearest 10 to match the step attribute.
|
||||||
|
Math.floor( parseInt( results.min_price, 10 ) / 10 ) * 10;
|
||||||
const maxConstraint = isLoading
|
const maxConstraint = isLoading
|
||||||
? undefined
|
? undefined
|
||||||
: parseInt( results.max_price, 10 );
|
: // Round down to nearest 10 to match the step attribute.
|
||||||
|
Math.ceil( parseInt( results.max_price, 10 ) / 10 ) * 10;
|
||||||
|
|
||||||
const onChange = useCallback(
|
const onChange = useCallback(
|
||||||
( prices ) => {
|
( prices ) => {
|
||||||
|
|
Loading…
Reference in New Issue