在React文档中,它说在受控组件中;React状态是"真理的单一来源";。这似乎是真的,除非在前导为零的情况下。在下面的示例中,您可以看到输入是受控制的,但在前导为零的情况下,输入值并不总是与状态值匹配。
测试
键入前导零,因此该值类似于0010
。
您可以看到state
中的值是整数10
,但输入显示的是0010
。
我的第一个想法是,这是因为组件实际上没有重新渲染,这是真的。10
和10
之间没有状态更改,因此没有新的渲染。这一点已得到证实,因为我们没有看到"render"console.log正在启动。
因此,让我们确保我们更改了值。添加一个2
,将0010
更改为00102
。状态中的值现在是102
,我们确认组件重新渲染。。。但是前导零仍然存在于输入中。
这似乎不一致,因为我希望输入中的值始终与状态中的值完全匹配。为什么会这样?从数字输入中删除前导零的可靠方法是什么?
// LEADING ZEROS INPUT TEST
// Step 1: type 0s into the input followed by any other digits
// Step 2: see that console log and val in `p` do not have leading 0's and input val does
const {useState} = React;
const App = () => {
const [val, setVal] = useState(10);
const handleChange = (evt) => {
const strVal = evt.currentTarget.value;
console.log('string', strVal, typeof strVal);
const intVal = parseInt(strVal, 10) || 0; // || 0 bc '' returns NaN
console.log('int', intVal, typeof intVal);
setVal(intVal);
}
console.log('render', val);
return (
<div>
<p>{val}</p>
<input
type="number"
value={val}
onChange={handleChange}
/>
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
既然您已经知道为什么,我将帮助您了解如何。
在我看来,从数字输入中修剪前导零的可靠方法是";在模糊上";,这侵扰性较小,并且提供了更好的用户体验。
const {useState, useCallback} = React;
const App = () => {
const [val, setVal] = useState(10);
const [strVal, setStrVal] = useState("10"); // To keep a reference of the real input value
const handleChange = (evt) => {
const inputVal = evt.currentTarget.value;
setStrVal(inputVal);
setVal(parseInt(evt.currentTarget.value, 10) || 0);
}
const handleBlur = useCallback((evt) => {
setStrVal(val.toString());
}, [val]);
return (
<div>
<p>{val}</p>
<input
type="number"
value={strVal}
onChange={handleChange}
onBlur={handleBlur}
/>
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>