cbd*_*per 6 javascript reactjs react-hooks
想象一下,我有一个自定义钩子,我将使用它向 HTML 元素中添加一个单击事件侦听器。
我用 来创建 ref const buttonRef = useRef(null);,所以第一次渲染时的值为空。ref 值仅在渲染方法的最后一个分配,在我的自定义钩子已经被调用的地方。
因此,在第一次渲染时,我的自定义钩子没有任何可以添加事件侦听器的内容。
我最终不得不在我的自定义钩子第二次运行之前更新组件,并最终将事件侦听器添加到元素。我得到以下行为:
题:
如何解决这个问题?我真的需要强制更新我的组件才能向自定义钩子发送 ref 吗?由于我只能在顶层调用钩子和自定义钩子(钩子规则),因此不允许使用以下内容。
useEffect(() => {
useMyHook();
});
Run Code Online (Sandbox Code Playgroud)
应用程序.js
function App() {
const buttonRef = useRef(null);
const hookValue = useMyHook(buttonRef.current);
const [forceUpdate, setForceUpdate] = useState(false);
return (
<div>
<button onClick={() => setForceUpdate(prevState => !prevState)}>
Update Component
</button>
<button ref={buttonRef}>Update Hook</button>
{"This is hook returned value: " + hookValue}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
useMyHook.js(自定义钩子)
import { useEffect, useState } from "react";
function useMyHook(element) {
const [myHookState, setMyHookState] = useState(0);
console.log("Inside useMyhook...");
console.log("This is the element received: " + element);
useEffect(() => {
console.log("Inside useMyhook useEffect...");
function onClick() {
setMyHookState(prevState => prevState + 1);
}
if (element !== null) {
element.addEventListener("click", onClick);
}
return () => {
console.log("Inside useMyhook useEffect return...");
if (element !== null) {
element.removeEventListener("click", onClick);
}
};
});
return myHookState;
}
export default useMyHook;
Run Code Online (Sandbox Code Playgroud)
解决方案非常简单,您只需要将 ref 传递给自定义钩子,而不是ref.current因为,当将 ref 分配给 DOM 并且自定义钩子中的 useEffect 被触发后, ref.current 在其原始引用处发生变异第一次渲染,因此buttonRef.current将引用 DOM 节点
使用MyHook.js
import { useEffect, useState } from "react";
function useMyHook(refEl) {
const [myHookState, setMyHookState] = useState(0);
console.log("Inside useMyhook...");
console.log("This is the element received: ", refEl);
useEffect(() => {
const element = refEl.current;
console.log("Inside useMyhook useEffect...");
function onClick() {
console.log("click");
setMyHookState(prevState => prevState + 1);
}
console.log(element);
if (element !== null) {
element.addEventListener("click", onClick);
}
return () => {
console.log("Inside useMyhook useEffect return...");
if (element !== null) {
element.removeEventListener("click", onClick);
}
};
}, []);
return myHookState;
}
export default useMyHook;
Run Code Online (Sandbox Code Playgroud)
索引.js
function App() {
const buttonRef = useRef(null);
const hookValue = useMyHook(buttonRef);
const [forceUpdate, setForceUpdate] = useState(false);
return (
<div>
<button onClick={() => setForceUpdate(prevState => !prevState)}>
Update Component
</button>
<button ref={buttonRef}>Update Hook</button>
{"This is hook returned value: " + hookValue}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4835 次 |
| 最近记录: |