I am quite new to react here. I am trying to constrain my input to min -10 and max 10 input value. I have it so the input can accept input and I am trying to use hooks useState and useEffect to try to change and set the value in the input. No matter what is in the input when you click off of it it should be constrained to -10 or 10. I know there is onBlur to trigger a function or state for that, but I don’t know where to go from there. Any help would be greatly appricated.
// For reference, this component is rendered
// by its parent like this:
//
// const ParentForm = () => {
// const [value, setValue] = useState(0)
// return (
// <NumberSelector
// min={-10}
// max={10}
// value={value}
// onChange={setValue}
// css={{ background: theme.white }}
// />
// )
// }
const NumberSelector = ({
min = -10,
max = 10,
value,
onChange: setValue,
className,
}) => {
const [tempValue, tempSetValue] = useState(0)
useEffect(() => {
}, [tempValue])
return (
<div
css={{
display: "flex",
border: `3px solid ${theme.richBlack}`,
borderRadius: 5,
}}
className={className}
>
<StepButton
aria-label="Reduce by one"
tabIndex="-1"
onClick={() => {
setValue((prev) => prev - 1)
}}
>
<svg width="16" height="16" viewBox="0 0 16 16">
<rect x="0" y="6.5" width="16" height="3" fill={theme.richBlack} />
</svg>
</StepButton>
<input
type="text"
maxLength={Math.max(min.toString().length, max.toString().length + 1)}
css={inputStyles}
value={tempValue}
onChange={(e) => tempSetValue(e.target.value)}
/>
<StepButton
aria-label="Increase by one"
tabIndex="-1"
onClick={() => {
setValue((prev) => prev + 1)
}}
>
<svg width="16" height="16" viewBox="0 0 16 16">
<rect x="0" y="6.5" width="16" height="3" fill={theme.richBlack} />
<rect x="6.5" y="0" width="3" height="16" fill={theme.richBlack} />
</svg>
</StepButton>
</div>
)
}
export default NumberSelector
NumberSelector.propTypes = {
min: PropTypes.number,
max: PropTypes.number,
value: PropTypes.number.isRequired,
onChange: PropTypes.func.isRequired,
className: PropTypes.string,
}
3
Answers
This has nothing to do with React.
As I understand you are looking for the numeric value. Then:
For more information Input type
Usually it isn’t recommended to use
useEffect
for any side-modifications.You can try having some custom handling in the
onChange
Obviously there’s room for improvement with the code, but that’s the gist of one way you can control the input value given to the setter.
If you want this to only happen after the user leaves the input, then you’ll just need to listen to another event (onFocusOut iirc?).
Hope this helped.
Since the
NumberSelector
component is completely controlled from the parent, you should not have local state to store the value. TheuseEffect
is also unnecessary.You can then attach an
onBlur
handler to clamp the value.For the increment and decrement buttons, you need to check that the value will not exceed the valid range after incrementing.