MouseEvent<HTMLElement> 给出错误超出最大调用堆栈大小
MouseEvent<HTMLElement> giving error Maximum call stack size exceeded
我正在将 React 中带有 MouseEvent<HTMLElement>
的按钮组件转换为使用 Hooks。但是,我现在在每次鼠标事件时收到 RangeError: Maximum call stack size exceeded
错误。
新密码是
const [isActive, setIsActive] = useState(false);
const [isFocus, setIsFocus] = useState(false);
const [isHover, setIsHover] = useState(false);
useEffect(() => {
if (autoFocus && button instanceof HTMLButtonElement) {
button.focus();
}
}, [autoFocus, button]);
const isInteractive = () => !isDisabled && !isLoading;
const onMouseEnter = (e: MouseEvent<HTMLElement>) => {
setIsHover(true);
if (onMouseEnter && !isHover) {
onMouseEnter(e);
}
};
const onMouseLeave = (e: MouseEvent<HTMLElement>) => {
setIsActive(false);
setIsHover(false);
if (onMouseLeave && isHover) {
onMouseLeave(e);
}
};
const onMouseDown = (e: MouseEvent<HTMLElement>) => {
e.preventDefault();
setIsActive(true);
if (onMouseDown && !isActive) {
onMouseDown(e);
}
};
const onMouseUp = (e: MouseEvent<HTMLElement>) => {
setIsActive(true);
if (onMouseUp && !isActive) {
onMouseUp(e);
}
};
const onFocus: FocusEventHandler<HTMLButtonElement> = event => {
setIsFocus(true);
if (onFocus) {
onFocus(event);
}
};
const onBlur: FocusEventHandler<HTMLButtonElement> = event => {
setIsFocus(false);
if (onBlur) {
onBlur(event);
}
};
const onInnerClick: MouseEventHandler<HTMLElement> = e => {
if (!isInteractive()) {
e.stopPropagation();
}
return true;
};
const StyledButton: ReactType = CustomComponent || getElement();
render() {
return (
<StyledButton
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onFocus={onFocus}
onBlur={onBlur}
>
{children}
</StyledButton>
);
};
而原始代码是(有效)
state = {
isActive: false,
isFocus: false,
isHover: false,
};
componentDidMount() {
if (this.props.autoFocus && this.button instanceof HTMLButtonElement) {
this.button.focus();
}
}
isInteractive = () => !this.props.isDisabled && !this.props.isLoading;
onMouseEnter = (e: React.MouseEvent<HTMLElement>) => {
this.setState({ isHover: true });
if (this.props.onMouseEnter) {
this.props.onMouseEnter(e);
}
};
onMouseLeave = (e: React.MouseEvent<HTMLElement>) => {
this.setState({ isHover: false, isActive: false });
if (this.props.onMouseLeave) {
this.props.onMouseLeave(e);
}
};
onMouseDown = (e: React.MouseEvent<HTMLElement>) => {
e.preventDefault();
this.setState({ isActive: true });
if (this.props.onMouseDown) {
this.props.onMouseDown(e);
}
};
onMouseUp = (e: React.MouseEvent<HTMLElement>) => {
this.setState({ isActive: false });
if (this.props.onMouseUp) {
this.props.onMouseUp(e);
}
};
onFocus: React.FocusEventHandler<HTMLButtonElement> = event => {
this.setState({ isFocus: true });
if (this.props.onFocus) {
this.props.onFocus(event);
}
};
onBlur: React.FocusEventHandler<HTMLButtonElement> = event => {
this.setState({ isFocus: false });
if (this.props.onBlur) {
this.props.onBlur(event);
}
};
onInnerClick: React.MouseEventHandler<HTMLElement> = e => {
if (!this.isInteractive()) {
e.stopPropagation();
}
return true;
};
const StyledButton: React.ReactType = CustomComponent || this.getElement();
render() {
return (
<StyledButton
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onFocus={onFocus}
onBlur={onBlur}
>
{children}
</StyledButton>
);
};
我在新代码中遗漏了什么导致 event
重复的钩子?
我认为问题出在您对 useEffect 的使用上。我认为您在 useEffect 中为 deps 数组提供的两个值是导致问题的原因。将被调用一次的 componentDidMount 的等价物是有一个空数组或根本没有数组。
这意味着将您的 useEffect 代码更改为如下
useEffect(() => {
if (autoFocus && button instanceof HTMLButtonElement) {
button.focus();
}
}, []);
这样做的原因是,如果这些值中的任何一个被更改,useEffect 将被再次调用,这将导致按钮和自动对焦(我假设)的重新渲染和重新评估,然后将再次调用 useEffect,从而导致无限递归.
可以在此处的第一个示例中找到更多信息https://reactjs.org/docs/hooks-effect.html#example-using-hooks
希望这对您有所帮助 :D
祝你好运!
注意:
我实际上没有 运行 你的代码,我只是假设这是问题所在
我正在将 React 中带有 MouseEvent<HTMLElement>
的按钮组件转换为使用 Hooks。但是,我现在在每次鼠标事件时收到 RangeError: Maximum call stack size exceeded
错误。
新密码是
const [isActive, setIsActive] = useState(false);
const [isFocus, setIsFocus] = useState(false);
const [isHover, setIsHover] = useState(false);
useEffect(() => {
if (autoFocus && button instanceof HTMLButtonElement) {
button.focus();
}
}, [autoFocus, button]);
const isInteractive = () => !isDisabled && !isLoading;
const onMouseEnter = (e: MouseEvent<HTMLElement>) => {
setIsHover(true);
if (onMouseEnter && !isHover) {
onMouseEnter(e);
}
};
const onMouseLeave = (e: MouseEvent<HTMLElement>) => {
setIsActive(false);
setIsHover(false);
if (onMouseLeave && isHover) {
onMouseLeave(e);
}
};
const onMouseDown = (e: MouseEvent<HTMLElement>) => {
e.preventDefault();
setIsActive(true);
if (onMouseDown && !isActive) {
onMouseDown(e);
}
};
const onMouseUp = (e: MouseEvent<HTMLElement>) => {
setIsActive(true);
if (onMouseUp && !isActive) {
onMouseUp(e);
}
};
const onFocus: FocusEventHandler<HTMLButtonElement> = event => {
setIsFocus(true);
if (onFocus) {
onFocus(event);
}
};
const onBlur: FocusEventHandler<HTMLButtonElement> = event => {
setIsFocus(false);
if (onBlur) {
onBlur(event);
}
};
const onInnerClick: MouseEventHandler<HTMLElement> = e => {
if (!isInteractive()) {
e.stopPropagation();
}
return true;
};
const StyledButton: ReactType = CustomComponent || getElement();
render() {
return (
<StyledButton
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onFocus={onFocus}
onBlur={onBlur}
>
{children}
</StyledButton>
);
};
而原始代码是(有效)
state = {
isActive: false,
isFocus: false,
isHover: false,
};
componentDidMount() {
if (this.props.autoFocus && this.button instanceof HTMLButtonElement) {
this.button.focus();
}
}
isInteractive = () => !this.props.isDisabled && !this.props.isLoading;
onMouseEnter = (e: React.MouseEvent<HTMLElement>) => {
this.setState({ isHover: true });
if (this.props.onMouseEnter) {
this.props.onMouseEnter(e);
}
};
onMouseLeave = (e: React.MouseEvent<HTMLElement>) => {
this.setState({ isHover: false, isActive: false });
if (this.props.onMouseLeave) {
this.props.onMouseLeave(e);
}
};
onMouseDown = (e: React.MouseEvent<HTMLElement>) => {
e.preventDefault();
this.setState({ isActive: true });
if (this.props.onMouseDown) {
this.props.onMouseDown(e);
}
};
onMouseUp = (e: React.MouseEvent<HTMLElement>) => {
this.setState({ isActive: false });
if (this.props.onMouseUp) {
this.props.onMouseUp(e);
}
};
onFocus: React.FocusEventHandler<HTMLButtonElement> = event => {
this.setState({ isFocus: true });
if (this.props.onFocus) {
this.props.onFocus(event);
}
};
onBlur: React.FocusEventHandler<HTMLButtonElement> = event => {
this.setState({ isFocus: false });
if (this.props.onBlur) {
this.props.onBlur(event);
}
};
onInnerClick: React.MouseEventHandler<HTMLElement> = e => {
if (!this.isInteractive()) {
e.stopPropagation();
}
return true;
};
const StyledButton: React.ReactType = CustomComponent || this.getElement();
render() {
return (
<StyledButton
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onFocus={onFocus}
onBlur={onBlur}
>
{children}
</StyledButton>
);
};
我在新代码中遗漏了什么导致 event
重复的钩子?
我认为问题出在您对 useEffect 的使用上。我认为您在 useEffect 中为 deps 数组提供的两个值是导致问题的原因。将被调用一次的 componentDidMount 的等价物是有一个空数组或根本没有数组。
这意味着将您的 useEffect 代码更改为如下
useEffect(() => {
if (autoFocus && button instanceof HTMLButtonElement) {
button.focus();
}
}, []);
这样做的原因是,如果这些值中的任何一个被更改,useEffect 将被再次调用,这将导致按钮和自动对焦(我假设)的重新渲染和重新评估,然后将再次调用 useEffect,从而导致无限递归.
可以在此处的第一个示例中找到更多信息https://reactjs.org/docs/hooks-effect.html#example-using-hooks
希望这对您有所帮助 :D 祝你好运!
注意: 我实际上没有 运行 你的代码,我只是假设这是问题所在