我做了一个定制的ReactJS钩子来处理几个特定的鼠标事件,如下所示:
const HealthcareServices = ({
filterToRemove,
filters,
onChange,
onClear,
selectedAmbulatoryCareFilterValue,
shouldClear,
}: Props): JSX.Element => {
const classes = useStyles();
...
useEffect(() => {
shouldClear && clearFilters();
}, [shouldClear]);
const useSingleAndDoubleClick = (actionSimpleClick: () => void, actionDoubleClick: () => void, delay = 250) => {
const [click, setClick] = useState(0);
useEffect(() => {
const timer = setTimeout(() => {
// simple click
if (click === 1) actionSimpleClick();
setClick(0);
}, delay);
// the duration between this click and the previous one
// is less than the value of delay = double-click
if (click === 2) actionDoubleClick();
return () => clearTimeout(timer);
}, [click]);
return () => setClick((prev) => prev + 1);
};
const handleSelectedItem = (service: Filter) => {
service.selected = !service.selected;
setHealthcareServices([...healthcareServices]);
onChange(healthcareServices);
};
const handleSingleClick = (service: Filter) => {
console.log('single-click');
if (service.isRequired) {
service.checkedIcon = <Icons.CheckboxSingleClick />;
}
handleSelectedItem(service);
};
const handleDoubleClick = (service: Filter) => {
console.log('double-click');
if (service.isRequired) {
service.checkedIcon = <Icons.CheckboxDoubleClick />;
}
handleSelectedItem(service);
};
const handleClick = (service: Filter) =>
useSingleAndDoubleClick(
() => handleSingleClick(service),
() => handleDoubleClick(service)
);
...
return (
<div className={classes.filter_container}>
...
<div className={classes.filter_subgroup}>
{filters.map((filter) => (
<div key={`${filter.label}-${filter.value}`} className={classes.filter}>
<Checkbox
label={filter.label}
className={classes.checkbox}
checked={filter.selected}
onChange={() => handleClick(filter)}
checkedIcon={filter.checkedIcon}
/>
</div>
))}
</div>
...
</div>
);
};当我点击我的<Checkbox />时,整个系统就崩溃了。错误是:
我的堆栈跟踪的顶部指向我的钩子中的useState。如果我把它移到外面,这个钩子看起来是:
const [click, setClick] = useState(0);
const useSingleAndDoubleClick = (actionSimpleClick: () => void, actionDoubleClick: () => void, delay = 250) => {
useEffect(() => {
const timer = setTimeout(() => {
// simple click
if (click === 1) actionSimpleClick();
setClick(0);
}, delay);
// the duration between this click and the previous one
// is less than the value of delay = double-click
if (click === 2) actionDoubleClick();
return () => clearTimeout(timer);
}, [click]);
return () => setClick((prev) => prev + 1);
};问题仍然发生,只有堆栈跟踪指向useEffect钩子。代码基于另一个答案here。
有什么建议吗?
发布于 2022-02-08 04:22:59
您已经在组件中定义了useSingleAndDoubleClick钩子。这不是你想做的。自定义钩子的思想是,您可以将逻辑移出组件之外,否则只能在组件内部发生。这有助于代码重用。
在函数中定义钩子是没有用的,因为钩子的神奇之处在于它们允许您访问状态变量以及通常只允许与内部函数组件交互的事情。
您需要在组件外部定义钩子并在组件中调用它,或者删除useSingleAndDoubleClick的定义,只需在组件中完成所有操作。
编辑:还有一个注意事项可以帮助澄清:这里您真正打破的规则是,您在您的useState函数中调用了其他挂钩(即,useSingleAndDoubleClick、useEffect)。尽管它被称为useSingleAndDoubleClick,但它实际上并不是一个钩子,因为它没有被创建或调用为一个钩子。因此,您不允许在其中调用其他钩子。
编辑:我在前面提到过这一点,但是下面是一个可以将钩子定义移出函数的示例:
编辑:还必须更改调用钩子的位置:不能在嵌套函数中调用钩子,但我不认为需要调用钩子。
const useSingleAndDoubleClick = (actionSimpleClick: () => void, actionDoubleClick: () => void, delay = 250) => {
const [click, setClick] = useState(0);
useEffect(() => {
const timer = setTimeout(() => {
// simple click
if (click === 1) actionSimpleClick();
setClick(0);
}, delay);
// the duration between this click and the previous one
// is less than the value of delay = double-click
if (click === 2) actionDoubleClick();
return () => clearTimeout(timer);
}, [click]);
return () => setClick((prev) => prev + 1);
};
const HealthcareServices = ({
filterToRemove,
filters,
onChange,
onClear,
selectedAmbulatoryCareFilterValue,
shouldClear,
}: Props): JSX.Element => {
const classes = useStyles();
...
useEffect(() => {
shouldClear && clearFilters();
}, [shouldClear]);
// your other handlers
// changed this - don't call the hook inside the function.
// your hook is returning the handler you want anyways, I think
const handleClick = useSingleAndDoubleClick(handleSingleClick, handleDoubleClick)https://stackoverflow.com/questions/71026732
复制相似问题