gpt4 book ai didi

javascript - 使用 React 钩子(Hook)设置状态后如何从组件调用事件?

转载 作者:行者123 更新时间:2023-12-04 10:37:06 24 4
gpt4 key购买 nike

我有两个 input s,其值反射(reflect)了计数器的状态。

第一个input设置状态立即随着其值(value)的变化。这个input可以表示应用程序的其他部分更改状态。

第二个input我制作的组件的一部分,名为 LazyInput . 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 , 但:
  • 如何调用onComplete(e)功能 – 与任何其他事件一样 – 来自 useEffect() ?
  • 仅当按下 ↑ ↓ 键而不是所有其他键时,我该怎么做?

  • 提前感谢您的帮助,这是 interactive sandbox .

    最佳答案

    我建议通过 countersetCounter下至 LazyInput因此可以直接访问它们。 useEffect可以给定一个依赖数组,仅当其依赖项之一发生更改时才会触发。但是,useEffect不适合这种情况。您可以分配 counter作为 useEffect 的依赖项但它会在每次 counter 的值时触发被改变。 useEffect只能观察变量,不能给它传值。我建议阅读这篇文章以了解 useEffect作品以及何时使用它。

    https://overreacted.io/a-complete-guide-to-useeffect/

    我的解决方案通过 countersetCounterLazyInput .如果你想要LazyInput要保留自己的状态,可以使用 useEffect观看lazyValue .当lazyValue更改,counter应该更新。

    这是我的解决方案:

    const {Fragment, useState, useEffect} = React;

    function LazyInput({ name, counter, setCounter }) {
    const [initialValue] = useState(counter);

    const handleKeyDown = e => {
    const { key, target } = e;

    switch (key) {
    case "ArrowUp": {
    setCounter(counter + 1);
    break;
    }
    case "ArrowDown": {
    setCounter(counter - 1);
    break;
    }
    case "Escape": {
    setCounter(initialValue);
    target.blur();
    break;
    }
    case "Enter": {
    target.blur();
    break;
    }
    default:
    return;
    }
    };
    return (
    <input
    name={name}
    value={counter}
    onChange={e => setCounter(e.target.value)}
    onKeyDown={e => handleKeyDown(e)}
    />
    );
    }

    function App() {
    const [counter, setCounter] = useState(0);

    return (
    <Fragment>
    <div>Counter: {counter}</div>
    <LazyInput name="counter" counter={counter} setCounter={setCounter} />
    <input
    value={counter}
    type="number"
    onChange={e => setCounter(parseFloat(e.target.value))}
    />
    </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>

    关于javascript - 使用 React 钩子(Hook)设置状态后如何从组件调用事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60119101/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com