限制React输入字段的最小和最大属性值取决于其父组件的设定。

huangapple go评论66阅读模式
英文:

How do I limit a React input field to a parent min and max props?

问题

以下是您提供的代码的翻译:

我在React中还很新我试图将输入限制为最小值-10和最大值10我已经使输入能够接受输入并尝试使用useState和useEffect钩子来尝试更改和设置输入中的值无论输入中包含什么内容当您点击离开它时它应该被限制为-10或10我知道有onBlur来触发一个函数或状态但我不知道从哪里开始任何帮助将不胜感激

// 供参考,此组件由其父组件呈现,如下所示:
//
// 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="减少一个"
        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="增加一个"
        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,
}

请注意,这是您提供的代码的中文翻译,不包括代码部分。如果您需要任何其他帮助,请告诉我。

英文:

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 = () =&gt; {
//   const [value, setValue] = useState(0)
//   return (
//     &lt;NumberSelector
//       min={-10}
//       max={10}
//       value={value}
//       onChange={setValue}
//       css={{ background: theme.white }}
//     /&gt;
//   )
// }
const NumberSelector = ({
min = -10,
max = 10,
value,
onChange: setValue,
className,
}) =&gt; {
const [tempValue, tempSetValue] = useState(0)
useEffect(() =&gt; {
}, [tempValue])
return (
&lt;div
css={{
display: &quot;flex&quot;,
border: `3px solid ${theme.richBlack}`,
borderRadius: 5,
}}
className={className}
&gt;
&lt;StepButton
aria-label=&quot;Reduce by one&quot;
tabIndex=&quot;-1&quot;
onClick={() =&gt; {
setValue((prev) =&gt; prev - 1)
}}
&gt;
&lt;svg width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot;&gt;
&lt;rect x=&quot;0&quot; y=&quot;6.5&quot; width=&quot;16&quot; height=&quot;3&quot; fill={theme.richBlack} /&gt;
&lt;/svg&gt;
&lt;/StepButton&gt;
&lt;input
type=&quot;text&quot;
maxLength={Math.max(min.toString().length, max.toString().length + 1)}
css={inputStyles}
value={tempValue}
onChange={(e) =&gt; tempSetValue(e.target.value)}
/&gt;
&lt;StepButton
aria-label=&quot;Increase by one&quot;
tabIndex=&quot;-1&quot;
onClick={() =&gt; {
setValue((prev) =&gt; prev + 1)
}}
&gt;
&lt;svg width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot;&gt;
&lt;rect x=&quot;0&quot; y=&quot;6.5&quot; width=&quot;16&quot; height=&quot;3&quot; fill={theme.richBlack} /&gt;
&lt;rect x=&quot;6.5&quot; y=&quot;0&quot; width=&quot;3&quot; height=&quot;16&quot; fill={theme.richBlack} /&gt;
&lt;/svg&gt;
&lt;/StepButton&gt;
&lt;/div&gt;
)
}
export default NumberSelector
NumberSelector.propTypes = {
min: PropTypes.number,
max: PropTypes.number,
value: PropTypes.number.isRequired,
onChange: PropTypes.func.isRequired,
className: PropTypes.string,
}

答案1

得分: 1

Sure, here is the translated content:

由于 NumberSelector 组件完全由父组件控制,因此不应该有本地状态来存储值。useEffect 也是不必要的。

然后,您可以附加一个 onBlur 处理程序来夹紧值。

<input
	type="text"
	maxLength={Math.max(min.toString().length, max.toString().length + 1)}
	value={value}
	onChange={e => setValue(e.target.value)}
	onBlur={e => {
	  if (value && !isNaN(value))
		setValue(Math.min(max, Math.max(min, value)));
	}}
/>

对于增加和减少按钮,您需要检查在增加后值不会超出有效范围。

<StepButton
	aria-label="减少一个"
	tabIndex="-1"
	onClick={() => setValue(Math.max(min, value - 1))}>
// ...
<StepButton
	aria-label="增加一个"
	tabIndex="-1"
	onClick={() => setValue(Math.min(max, value + 1))}>

Note: I've left the code parts untranslated as per your request.

英文:

Since the NumberSelector component is completely controlled from the parent, you should not have local state to store the value. The useEffect is also unnecessary.

You can then attach an onBlur handler to clamp the value.

&lt;input
	type=&quot;text&quot;
	maxLength={Math.max(min.toString().length, max.toString().length + 1)}
	value={value}
	onChange={e =&gt; setValue(e.target.value)}
	onBlur={e =&gt; {
	  if (value &amp;&amp; !isNaN(value))
		setValue(Math.min(max, Math.max(min, value)));
	}}
/&gt;

For the increment and decrement buttons, you need to check that the value will not exceed the valid range after incrementing.

&lt;StepButton
	aria-label=&quot;Reduce by one&quot;
	tabIndex=&quot;-1&quot;
	onClick={() =&gt; setValue(Math.max(min, value - 1))}&gt;
// ...
&lt;StepButton
	aria-label=&quot;Increase by one&quot;
	tabIndex=&quot;-1&quot;
	onClick={() =&gt; setValue(Math.min(max, value + 1))}&gt;

答案2

得分: 0

这与React无关。

据我理解,您正在寻找数值。然后:

<input
    type="number"
    min={min}
    max={max}
    css={inputStyles}
    value={tempValue}
    onChange={(e) => tempSetValue(e.target.value)}
/>

有关更多信息,请参阅输入类型

英文:

This has nothing to do with React.

As I understand you are looking for the numeric value. Then:

 &lt;input
type=&quot;number&quot;
min={min}
max={max}
css={inputStyles}
value={tempValue}
onChange={(e) =&gt; tempSetValue(e.target.value)}
/&gt;

For more information Input type

答案3

得分: 0

Usually it isn't recommended to use useEffect for any side-modifications.

You can try having some custom handling in the onChange:

const onTempChange = (e) => {
    // default to 1 if no input is entered
    let tempFloat = parseFloat(e.target.value || '1');
    // default to 1 if input is invalid
    if (isNaN(tempFloat)) {
        tempFloat = 1;
    } else {
        tempFloat = Math.min(max, Math.max(min, tempFloat));
    }
    // usually you name the setter something like setTempValue
    tempSetValue(tempFloat);
};

return (
    // ...
    <input ... onChange={onTempChange} />
);

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.

英文:

Usually it isn't recommended to use useEffect for any side-modifications.

You can try having some custom handling in the onChange

const onTempChange = (e) =&gt; {
    // default to 1 if no input is entered
    let tempFloat = parseFloat(e.target.value || &#39;1&#39;);
    // default to 1 if input is invalid
    if (isNan(tempFloat) {
        tempFloat = 1;
    } else {
        tempFloat = Math.min(max, Math.max(min, tempFloat));
    }
    // usually you name the setter something like setTempValue
    tempSetValue(tempFloat);
};

return (
    // ...
    &lt;input ... onChange={onTempChange} /&gt;
);

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.

huangapple
  • 本文由 发表于 2023年5月25日 07:10:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76327933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定