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

React18中Invalid hook call错误及组件不重渲染问题求助

问题分析与解决方案

错误根源

你在MapStateToProps这个普通函数中调用了useParams(),违反了React Hook的核心规则:Hook只能在函数组件的顶层代码或自定义Hook内部调用,普通辅助函数里不能使用Hook,这就是控制台抛出Invalid hook call错误的原因。

同时,因为MapStateToProps无法正确获取到路由ID,导致返回的expense数据始终无法和redux状态同步,这也是编辑后组件不重渲染的直接原因。

解决方案

方案1:改用React-Redux Hook写法(推荐,适配React18+)

直接使用useSelector和useDispatch替代传统的connect,在组件内直接获取路由参数与redux状态,代码更简洁直观:

import { useSelector, useDispatch } from "react-redux";
import { useParams } from "react-router-dom";
import ExpenseForm from "./ExpenseForm";
import { editExpense, removeExpense } from '../actions/expenses';
import { useNavigate } from 'react-router-dom';

function EditExpensePage (){
  const { id } = useParams();
  const navigate = useNavigate();
  // 从redux状态中筛选当前ID对应的费用项
  const expense = useSelector(state => state.expenses.find(exp => exp.id === id));
  const dispatch = useDispatch();

  return(
    <div>
      <ExpenseForm 
        expense={expense}
        onSubmit={(expense) =>{
          dispatch(editExpense(id, expense));
          navigate('/');
        }}
      />

      <button onClick={()=>{
        dispatch(removeExpense({id: expense.id}));
        navigate('/');
      }}>Remove</button>
    </div>
  );
};

export default EditExpensePage;

方案2:修复传统connect写法

如果需要保留connect的使用方式,需要将路由ID从组件传递给MapStateToProps(它可以接收第二个参数ownProps,即组件的props):

import { connect } from "react-redux";
import { useParams } from "react-router-dom";
import ExpenseForm from "./ExpenseForm";
import { editExpense, removeExpense } from '../actions/expenses';
import { useNavigate } from 'react-router-dom';

function EditExpensePage (props){
  const { id } = useParams();
  const navigate = useNavigate();

  return(
    <div>
      <ExpenseForm 
        expense={props.expense}
        onSubmit={(expense) =>{
          props.dispatch(editExpense(id, expense));
          navigate('/');
        }}
      />

      <button onClick={()=>{
        props.dispatch(removeExpense({id: props.expense.id}));
        navigate('/');
      }}>Remove</button>
    </div>
  );
};

// 通过ownProps接收组件传递的ID,筛选对应费用项
function MapStateToProps(state, ownProps) {
  return{
    expense: state.expenses.find((expense) => expense.id === ownProps.id)
  };
};

// 包装组件,将路由ID作为props传递给MapStateToProps
export default connect(MapStateToProps)((props) => {
  const { id } = useParams();
  return <EditExpensePage {...props} id={id} />;
});

效果说明

修复后,当你执行编辑操作时,redux状态会更新,组件会自动感知到状态变化并重新渲染,展示修改后的费用数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:18:34