[英]React hook form: How to can I use onChange on React Hook Form Version 7.0
[英]How can I use a Mutex with a react hook?
我想确保一段代码不会同时运行。 async-Mutex 库似乎对我不起作用。 这是一个最小的复制:
/* eslint-disable */
import React, { useState, useEffect } from "react";
var Mutex = require("async-mutex").Mutex;
const Timer = () => {
const [isActive, setIsActive] = useState(false);
const mutex = new Mutex();
useEffect(() => {
mutex.runExclusive(async function () {
console.log("starting", isActive);
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log("ending", isActive);
});
}, [isActive]);
return (
<div className="app">
<button onClick={() => setIsActive((prev) => !prev)} type="button">
{isActive ? "Active" : "Inactive"}
</button>
</div>
);
};
export { Timer as default };
如果你快速点击按钮两次,你可以看到它会打印
starting
true
starting
false
starting
true
ending
true
ending
false
你可以看到这些是交错的。
我怎样才能强制它不同时运行?
问题很可能是因为在每次重新渲染时都分配了互斥锁,从而为您提供了一个新实例。
你可以移动const mutex = new Mutex();
在您的组件之外,为您的所有 Timer 组件提供一个全局版本,这意味着 Timer 可以相互阻止。
您可以通过将互斥锁实例包装在React.useMemo
钩子中来使互斥锁实例在整个重新渲染过程中保持稳定,这将使每个 Timer 组件都有自己的互斥锁,这意味着 Timer 不能相互阻止,只能阻止自己。
将组件内的声明替换为:
const mutex = React.useMemo(() => new Mutex(), []);
然后在useEffect
中将互斥体添加到您的依赖数组中:
useEffect(() => {
// Your code
}, [isActive, mutex]);
import React, { useState, useEffect, useRef, useMemo} from "react";
var Mutex = require("async-mutex").Mutex;
const Timer = () => {
const [isActive, setIsActive] = useState(false);
const mutex = useRef(new Mutex());
// Or another way, it might be a bit more performant,
// although the Mutex class has an almost empty constructor
// const mutex= useMemo(()=> new Mutex(), []);
useEffect(() => {
mutex.current.runExclusive(async function () {
console.log("starting", isActive);
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log("ending", isActive);
});
}, [isActive]);
return (
<div className="app">
<button onClick={() => setIsActive((prev) => !prev)} type="button">
{isActive ? "Active" : "Inactive"}
</button>
</div>
);
};
export { Timer as default };
如果您想取消之前的 function 调用并支持卸载时的异步例程清理( 演示):
/* eslint-disable */
import React, { useState, useEffect } from "react";
import CPromise from "c-promise2";
import { useAsyncEffect, useAsyncCallback } from "use-async-effect2";
export default function Timer() {
const [isActive, setIsActive] = useState(false);
const callback = useAsyncCallback(
function* () {
console.log("starting", isActive);
yield CPromise.delay(1000);
console.log("ending", isActive);
},
{ combine: true }
);
useAsyncEffect(
function* () {
console.log("mount");
yield callback();
},
[isActive]
);
return (
<div className="app">
<button onClick={() => setIsActive((prev) => !prev)} type="button">
{isActive ? "Active" : "Inactive"}
</button>
</div>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.