tajo / react-range

🎚️Range input with a slider. Accessible. Bring your own styles and markup.
https://react-range.pages.dev
MIT License
857 stars 97 forks source link

Property 'Values' in conflict #96

Open iamterryclark opened 4 years ago

iamterryclark commented 4 years ago

Hey,

I am using react-range with a min / max of 0 and 1 and a step of 0.001. the values I am sending is within an array.

[0.66, 0.947]

I seem to get the warning appear on component load. Am I missing something as this seems in range to me..

Thanks in advance

tajo commented 4 years ago

Something's broken about multiple thumbs and decimals.

raptor3790 commented 4 years ago

Any news on this issue?

swashata commented 3 years ago

I can say that this is due to floating point arithmetic in JavaScript.

Let's say, my config is like this

{
    min: 97,
    max: 108,
    step: 0.1,
    values: [98.6],
}

During the calculation at

https://github.com/tajo/react-range/blob/57345c307972c84acf333bfd3793b0784a0b4b56/src/Range.tsx#L91-L97

It becomes

https://github.com/tajo/react-range/blob/57345c307972c84acf333bfd3793b0784a0b4b56/src/utils.ts#L17-L20

const res = (max - min) / step;
// (98.6 - 97) / 0.1
// 15.999999999999943
return parseInt(res.toString(), 10) === res;
// 15 === 15.999999999999943
// false

One possible solution is to take a precision prop from userland and multiply the numbers to convert floats to integer.

Like

const multiplier = 10 ** precision;
const normalizedMax = Math.round(max * multiplier);
const normalizedMin = Math.round(min * multiplier);
const normalizedStep = Math.round(step * multiplier);
const res = (max - min) / step;
// (986 - 970) / 1
// 16
return parseInt(res.toString(), 10) === res;
// 16 === 16
// true

I have forked this library and made such changes. I cannot think of any other method where I can reliably extract number of decimal points from given values.