为什么这个输入 "value" 属性 没有刷新?
Why is the this input "value" property not refreshed?
我在用它做一个新项目时正在学习 React。
我想创建一个输入组件,其事件仅在用户退出输入或按下回车键时触发。 (here is the link to codesandbox)
const MyInput = ({ value, onValueChange }) => {
const [myCurrentTypingValue, setMyCurrentTypingValue] = useState(value);
useEffect(() => setMyCurrentTypingValue(value), [value]);
const commitChanges = () => {
const numericValue = Number(myCurrentTypingValue);
setMyCurrentTypingValue(numericValue);
if (value !== numericValue) onValueChange(numericValue);
};
const handleOnChange = (e) => setMyCurrentTypingValue(e.target.value);
const handleOnBlur = () => commitChanges();
const handleOnKeyPress = (e) => {
if (e.charCode === 13) commitChanges();
};
return (
<input
type="number"
value={myCurrentTypingValue}
onChange={handleOnChange}
onBlur={handleOnBlur}
onKeyPress={handleOnKeyPress}
/>
);
};
如你所见,当我输入一些东西时,当我按回车或退出时输入正确显示,但是当我输入以0开头的数字(例如000023)时,虽然数值被正确转换,它仍然显示为前面全为零。
因为我改变了我的组件的状态,我希望我的输入框值属性被刷新,但它不是:
为什么会这样?我用调试器工具检查过,我的状态是正确的吗?
如何让输入框以正确的数字格式值反映新状态?
当需要“提交”您的更改时,您应该将已解析的 number
值字符串化并更新输入值(始终为 string
)。这是一个 self-contained 示例:
body { font-family: sans-serif; }
input[type="number"], pre { font-size: 1rem; padding: 0.5rem; }
<div id="root"></div><script src="https://unpkg.com/react@18.1.0/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@18.1.0/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.17.10/babel.min.js"></script>
<script type="text/babel" data-type="module" data-presets="env,react">
// import * as ReactDOM from 'react-dom/client';
// import {useEffect, useState} from 'react';
// This Stack Overflow snippet demo uses UMD modules instead of the above import statments
const {useEffect, useState} = React;
// Parse a string as a number, but if the string is not a valid number then return 0
function parseNumber (str) {
const n = Number(str);
return Number.isNaN(n) ? 0 : n;
}
function NumberInput ({value, setValue}) {
const [rawValue, setRawValue] = useState(String(value));
useEffect(() => setRawValue(String(value)), [value]);
const commit = () => setValue(parseNumber(rawValue));
const handleChange = (ev) => setRawValue(ev.target.value);
const handleKeyUp = (ev) => {
if (ev.key === 'Enter') commit();
};
return (
<input
type="number"
onBlur={commit}
onChange={handleChange}
onKeyUp={handleKeyUp}
value={rawValue}
/>
);
}
function App () {
const [value, setValue] = useState(0);
return (
<div>
<h1>Number input management</h1>
<NumberInput {...{value, setValue}} />
<pre><code>{JSON.stringify({value}, null, 2)}</code></pre>
</div>
);
}
const reactRoot = ReactDOM.createRoot(document.getElementById('root'));
reactRoot.render(<App />);
</script>
我在用它做一个新项目时正在学习 React。
我想创建一个输入组件,其事件仅在用户退出输入或按下回车键时触发。 (here is the link to codesandbox)
const MyInput = ({ value, onValueChange }) => {
const [myCurrentTypingValue, setMyCurrentTypingValue] = useState(value);
useEffect(() => setMyCurrentTypingValue(value), [value]);
const commitChanges = () => {
const numericValue = Number(myCurrentTypingValue);
setMyCurrentTypingValue(numericValue);
if (value !== numericValue) onValueChange(numericValue);
};
const handleOnChange = (e) => setMyCurrentTypingValue(e.target.value);
const handleOnBlur = () => commitChanges();
const handleOnKeyPress = (e) => {
if (e.charCode === 13) commitChanges();
};
return (
<input
type="number"
value={myCurrentTypingValue}
onChange={handleOnChange}
onBlur={handleOnBlur}
onKeyPress={handleOnKeyPress}
/>
);
};
如你所见,当我输入一些东西时,当我按回车或退出时输入正确显示,但是当我输入以0开头的数字(例如000023)时,虽然数值被正确转换,它仍然显示为前面全为零。
因为我改变了我的组件的状态,我希望我的输入框值属性被刷新,但它不是:
为什么会这样?我用调试器工具检查过,我的状态是正确的吗?
如何让输入框以正确的数字格式值反映新状态?
当需要“提交”您的更改时,您应该将已解析的 number
值字符串化并更新输入值(始终为 string
)。这是一个 self-contained 示例:
body { font-family: sans-serif; }
input[type="number"], pre { font-size: 1rem; padding: 0.5rem; }
<div id="root"></div><script src="https://unpkg.com/react@18.1.0/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@18.1.0/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.17.10/babel.min.js"></script>
<script type="text/babel" data-type="module" data-presets="env,react">
// import * as ReactDOM from 'react-dom/client';
// import {useEffect, useState} from 'react';
// This Stack Overflow snippet demo uses UMD modules instead of the above import statments
const {useEffect, useState} = React;
// Parse a string as a number, but if the string is not a valid number then return 0
function parseNumber (str) {
const n = Number(str);
return Number.isNaN(n) ? 0 : n;
}
function NumberInput ({value, setValue}) {
const [rawValue, setRawValue] = useState(String(value));
useEffect(() => setRawValue(String(value)), [value]);
const commit = () => setValue(parseNumber(rawValue));
const handleChange = (ev) => setRawValue(ev.target.value);
const handleKeyUp = (ev) => {
if (ev.key === 'Enter') commit();
};
return (
<input
type="number"
onBlur={commit}
onChange={handleChange}
onKeyUp={handleKeyUp}
value={rawValue}
/>
);
}
function App () {
const [value, setValue] = useState(0);
return (
<div>
<h1>Number input management</h1>
<NumberInput {...{value, setValue}} />
<pre><code>{JSON.stringify({value}, null, 2)}</code></pre>
</div>
);
}
const reactRoot = ReactDOM.createRoot(document.getElementById('root'));
reactRoot.render(<App />);
</script>