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
相关产品推荐
相关产品推荐

