mik*_*ell 2 javascript reactjs redux react-hooks use-effect
我有一个 React/Redux 类组件,我正在将其转换为功能组件。
\n以前,它有一个componentDidMount回调,为从应用程序中其他地方调度的自定义事件添加事件侦听器。这正在被替换useEffect。事件侦听器在触发时调用该组件中其他位置的方法。
此方法执行的操作取决于从选择器检索的值。最初,我传递了useEffect一个空的依赖项数组,因此它只会在挂载上添加事件侦听器。然而,显然这会导致选择器值周围的闭包过时。一个可行的解决方案是将选择器作为依赖项 \xe2\x80\x93 传递给它,但是,这会导致每次选择器的值更改时都会删除/重新添加侦听器,这不太好。
我正在尝试考虑一种解决方案,该解决方案仅添加一次事件侦听器,同时允许被调用的方法访问选择器的当前值。
\n示例代码:
\nconst currentValue = useSelector(state => getValue(state));\n\nuseEffect(() => {\n document.addEventListener('my.custom.event', handleEvent);\n\n return(() => document.removeEventListener('my.custom.event', handleEvent));\n}, []);\n\nconst handleEvent = () => {\n console.log(currentValue)\n}\nRun Code Online (Sandbox Code Playgroud)\n事实上,这会创建一个陈旧的闭包currentValue,以便在事件触发时,记录的值不一定是最新的。
更改[]为[currentValue]inuseEffect会产生预期的行为,但会在每次更改 时删除/重新添加事件侦听器currentValue。
由于这不是组件的状态值,因此无法选择使用回调(例如console.log(currentValue => console.log(currentValue))访问最新值)。我还尝试使用 usinguseRef来保留该值,但我相信每次选择器的值发生变化时我都需要某种方法来更新 ref 值,这并不是一个解决方案。
在实际组件中, 的值currentValue在 Redux 中被其他组件修改,因此将其更改为状态值也不太可行。
我在想:
\ncomponentDidMount不会遇到过时的关闭问题。)该useRef方法通常是此问题的解决方案,但您需要另一个方法useEffect来更新引用currentValue:
const currentValue = useSelector(state => getValue(state));
const valueRef = useRef();
useEffect(() => { valueRef.current = currentValue; }, [currentValue]);
useEffect(() => {
const handleEvent = () => {
console.log(valueRef.current)
}
document.addEventListener('my.custom.event', handleEvent);
return(() => document.removeEventListener('my.custom.event', handleEvent));
}, []);
Run Code Online (Sandbox Code Playgroud)
但是,您也可以从 中提取整个函数useEffect,并在钩子中使用它,这样您就可以轻松创建用于事件处理的自定义钩子:
const useEventHandler = (eventName, eventHandler, eventTarget = document) => {
const eventHandlerRef = useRef();
useEffect(() => {
eventHandlerRef.current = eventHandler;
});
useEffect(() => {
const handleEvent = (...args) => eventHandlerRef?.current(...args);
eventTarget.addEventListener(eventName, handleEvent);
return (() => eventTarget.removeEventListener(eventName, handleEvent));
}, []);
}
Run Code Online (Sandbox Code Playgroud)
使用钩子:
const currentValue = useSelector(state => getValue(state));
useEventHandler('my.custom.event', () => console.log(currentValue))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2187 次 |
| 最近记录: |