使用 useEffect() 挂钩处理键事件的正确方法是什么,而另一方面触发本地状态更改?

What is the correct way to handle a key event using useEffect() hook which on the other hand triggers local state changes?

React Hooks 很新,我 运行 对此问题感兴趣。我有一个功能组件,当我按下回车键(keycode = 13)时,它接受输入并将其发送到父组件。该组件看起来像这样。

const SearchTermBar = (props) => {
const {resetStateSearchTerm, handlePowerToggleParent} = props;
const [inputTerm, handleInputChange] = useState('');
const inputRef = useRef();

useEffect(() => {
    const keyPressEvent = (e) => {
        if (e.keyCode === 13) {
            resetStateSearchTerm(inputTerm);
            handleInputChange('');
            handlePowerToggleParent('search');
        }
    };

    inputRef.current.addEventListener('keydown', keyPressEvent);
    let parentInputRef = inputRef;

    return () => {
        console.log('remove event listener');
        parentInputRef.current.removeEventListener('keydown', keyPressEvent);
    }
}, [inputTerm, resetStateSearchTerm, handlePowerToggleParent]);

return (
    <div className='SearchTermBar'>
        <input
            type='text'
            placeholder='Enter search term here (Press return to confirm)'
            className='SearchTermBar__Input'
            value={inputTerm}
            onChange={(e) => handleInputChange(e.target.value)}
            ref={inputRef}
        />
    </div>
);

问题是每次 inputTermprops 值更改时都会注册和注销事件。但是我无法找出处理事件 registration/removal 的正确方法(理想情况下应该发生一次)我理解这是因为对 inputTerm 的依赖,但我想知道更好的方法这个问题的解决方案。

您已经有了输入参考,您真的不需要状态:

const NOP = () => {};
const DEFAULT_INPUT = "";

function SearchTermBar(props) {
  const { resetStateSearchTerm = NOP, handlePowerToggleParent = NOP } = props;
  const inputRef = useRef();

  useEffect(() => {
    const keyPressEvent = (e) => {
      if (e.keyCode === 13) {
        resetStateSearchTerm(inputRef.current.value);
        inputRef.current.value = DEFAULT_INPUT;
        handlePowerToggleParent("search");
      }
    };

    inputRef.current.addEventListener("keydown", keyPressEvent);
    let parentInputRef = inputRef;

    return () => {
      console.log("remove event listener");
      parentInputRef.current.removeEventListener("keydown", keyPressEvent);
    };
  }, [resetStateSearchTerm, handlePowerToggleParent]);

  return (
    <input
      type="text"
      placeholder="Enter search term here (Press return to confirm)"
      style={{ width: "50%" }}
      ref={inputRef}
    />
  );
}

无论哪种方式,如果你想保持状态,它的值应该被复制到一个 ref 中以修复 useEffect 中的闭包。可以通过添加另一个 useEffect 来完成,这将更新提到的 ref.