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 祝你好运!

注意: 我实际上没有 运行 你的代码,我只是假设这是问题所在