使用 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>
);
问题是每次 inputTerm
或 props
值更改时都会注册和注销事件。但是我无法找出处理事件 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.
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>
);
问题是每次 inputTerm
或 props
值更改时都会注册和注销事件。但是我无法找出处理事件 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.