我有两个input
,其值反映了计数器的状态。其中一个是名为LazyInput
的组件的一部分,该组件不会仅在输入模糊时立即更新状态。但是,我希望LazyInput
不会表现得很“懒惰”,并且只要通过↑ ↓键更改值,就立即立即更新计数器。
App
代码(包括普通的input
)如下:
const {Fragment, useState, useEffect} = React;
function LazyInput({ name, value, onComplete }) {
const initialValue = value;
const [lazyValue, setLazyValue] = useState(value);
// Sync to state changed by the regular input
useEffect(() => {
setLazyValue(value);
}, [value]);
const handleKeyDown = e => {
const { key, target } = e;
switch (key) {
case "ArrowUp": {
setLazyValue(parseFloat(lazyValue) + 1);
onComplete(e);
break;
}
case "ArrowDown": {
setLazyValue(parseFloat(lazyValue) - 1);
onComplete(e);
break;
}
case "Escape": {
setLazyValue(initialValue);
target.blur();
break;
}
case "Enter": {
target.blur();
break;
}
default:
return;
}
};
return (
<input
name={name}
value={lazyValue}
onChange={e => setLazyValue(e.target.value)}
onKeyDown={e => handleKeyDown(e)}
onBlur={e => onComplete(e)}
/>
);
}
function App() {
const [counter, setCounter] = useState(0);
function handleCounterChange(e) {
setCounter(parseFloat(e.target.value));
}
return (
<Fragment>
<div>Counter: {counter}</div>
<LazyInput
name="counter"
value={counter}
onComplete={e => handleCounterChange(e)}
/>
<input
value={counter}
type="number"
onChange={e => handleCounterChange(e)}
/>
</Fragment>
);
}
ReactDOM.render(<App />, document.getElementById("app"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="app"></div>
按↑ ↓键会在onComplete(e)
之前触发setLazyValue()
功能–我想是因为它是异步的–与状态失去同步。
出于相同的原因,按Esc会使input
模糊,然后将其值重置为initialValue
。
我知道setState()
类回调has been substituted by the useEffect()
hook,但:
useEffect()
调用onComplete(e)
功能?感谢您的帮助,这里是useEffect()
。
我建议将interactive sandbox和counter
传递给setCounter
。然后LazyInput
可以使用useEffect
作为依赖项。每当更改counter
时,counter
挂钩就会触发。
useEffect
function LazyInput({ name, counter, setCounter}) {
const [initialValue] = useState(counter);
// Sync to state changed by the regular input
useEffect(() => {
target.blur();
}, [counter]);
const handleKeyDown = e => {
const { key, target } = e;
switch (key) {
case "ArrowUp": {
setCounter(parseFloat(counter) + 1);
break;
}
case "ArrowDown": {
setCounter(parseFloat(counter) - 1);
break;
}
case "Escape": {
setCounter(initialValue);
break;
}
case "Enter": {
target.blur();
break;
}
default:
return;
}
...