You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React报错Invalid hook call,该如何排查并解决?

问题原因

你当前的报错是违反了React Hook的使用规则导致的。Hook只能在React函数组件的顶层作用域,或者自定义Hook的顶层调用,不能在普通函数、事件回调、类组件内部直接调用。你在普通事件处理函数HandleAdd内部调用了useState,触发了规则校验。
你的依赖中React和React DOM版本均为17.0.2,版本匹配,也没有多副本问题,因此只需要修改Hook的调用位置即可解决报错。

修复方案

方案1:保留类组件写法,将状态迁移到类组件的state中

将HandleAdd的逻辑整合为CustomToolbar的类方法,用类组件自身的state管理原本的reRender状态,修改后代码如下:

class CustomToolbar extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      reRender: false
    }
  }

  handleAdd = () => {
    Swal.fire({
      title: 'Add Department',
      text: "Input department name below.",
      showCancelButton: true,
      confirmButtonColor: '#3085d6',
      cancelButtonColor: '#d33',
      confirmButtonText: 'Save',
      html: generateInputForms({
        strname: '',
        intsequence: ''
      }),
      preConfirm: () => {
        let strname = document.getElementById('strname').value;
        let intsequence = document.getElementById('intsequence').value;

        if (!strname) {
          Swal.showValidationMessage('The Department field is required.')
        }
        if (!intsequence) {
          Swal.showValidationMessage('The Sequence field is required.')
        }
        return {
          strname: strname,
          intsequence: intsequence
        }
      }
    }).then((result) => {
      if (result.isConfirmed) {
        let request = {
          strresourcename: "Richard",
          strapplicationcode: "SchoolApp",
          strmodulename: "Department",
          strtablename: "fmDepartments",
          strfieldid: "fmDepartmentsId",
          strname: document.getElementById('strname').value,
          intsequence: document.getElementById('intsequence').value
        }
        addDepartment(request).then(function(res){
          if (res.status == 200){
            Swal.fire({
              icon: 'success',
              title: 'Department',
              text: 'New Department has been added successfully.',
            }).then(() => {
              this.setState(prev => ({reRender: !prev.reRender}));
            })
          }else{
            Swal.fire({
              icon: 'error',
              title: 'Oops',
              text: 'Something went wrong.',
            })
          }
        })
      }
    })
  }

  render() {
    const { classes } = this.props;
    return (
      <React.Fragment>
        <Tooltip title={"Add"}>
            <Button
              variant="contained"
              color="primary"
              size="small"
              style={{
                textTransform: 'unset',
                outline: 'none',
                marginLeft: 20,
                backgroundColor: '#00B029',
              }}
              onClick={this.handleAdd}
              className={classes.button}
              startIcon={<AddIcon className={classes.addIcon} style={{color: '#fff',}} />}
            >
              Add
            </Button>
        </Tooltip>
      </React.Fragment>
    );
  }
}
export default withStyles(defaultToolbarStyles, { name: "CustomToolbar" })(CustomToolbar);

方案2:将类组件重构为函数组件(适合后续有更多Hook使用需求的场景)

如果后续需要用到更多Hook,可以直接把CustomToolbar改成函数组件,就能直接在组件内部使用useState等Hook,修改后代码如下:

const CustomToolbar = (props) => {
  const { classes } = props;
  const [reRender, setRerender] = useState(false);

  const handleAdd = () => {
    Swal.fire({
      title: 'Add Department',
      text: "Input department name below.",
      showCancelButton: true,
      confirmButtonColor: '#3085d6',
      cancelButtonColor: '#d33',
      confirmButtonText: 'Save',
      html: generateInputForms({
        strname: '',
        intsequence: ''
      }),
      preConfirm: () => {
        let strname = document.getElementById('strname').value;
        let intsequence = document.getElementById('intsequence').value;

        if (!strname) {
          Swal.showValidationMessage('The Department field is required.')
        }
        if (!intsequence) {
          Swal.showValidationMessage('The Sequence field is required.')
        }
        return {
          strname,
          intsequence
        }
      }
    }).then((result) => {
      if (result.isConfirmed) {
        const { strname, intsequence } = result.value;
        let request = {
          strresourcename: "Richard",
          strapplicationcode: "SchoolApp",
          strmodulename: "Department",
          strtablename: "fmDepartments",
          strfieldid: "fmDepartmentsId",
          strname,
          intsequence
        }
        addDepartment(request).then(function(res){
          if (res.status == 200){
            Swal.fire({
              icon: 'success',
              title: 'Department',
              text: 'New Department has been added successfully.',
            }).then(() => {
              setRerender(prev => !prev);
            })
          }else{
            Swal.fire({
              icon: 'error',
              title: 'Oops',
              text: 'Something went wrong.',
            })
          }
        })
      }
    })
  }

  return (
    <React.Fragment>
      <Tooltip title={"Add"}>
          <Button
            variant="contained"
            color="primary"
            size="small"
            style={{
              textTransform: 'unset',
              outline: 'none',
              marginLeft: 20,
              backgroundColor: '#00B029',
            }}
            onClick={handleAdd}
            className={classes.button}
            startIcon={<AddIcon className={classes.addIcon} style={{color: '#fff',}} />}
          >
            Add
          </Button>
      </Tooltip>
    </React.Fragment>
  );
}

export default withStyles(defaultToolbarStyles, { name: "CustomToolbar" })(CustomToolbar);

内容的提问来源于stack exchange,提问作者user15404864

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 10:24:04