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

React中用recompose的compose在mapStateToProps获取URL参数并保护路由

搞定路由保护+参数获取的组合问题

嘿,我之前也碰到过一模一样的情况!问题大概率出在recompose的compose函数里高阶组件的顺序——因为compose是从右往左执行的,顺序错了的话,connect就拿不到路由的ownProps了。下面给你一步步捋清楚怎么解决:

第一步:先确保你的withAuthorization能正确传props

首先得确认你的withAuthorization是个合格的高阶组件,能把收到的所有props都传给被包裹的组件,而且要用上withRouter来拿到路由相关的history这些东西,比如大概写成这样:

const withAuthorization = (condition) => (Component) => {
  class WithAuthorization extends React.Component {
    componentDidMount() {
      // 未认证就跳登录页
      if (!condition(this.props)) {
        this.props.history.push('/login');
      }
    }

    componentDidUpdate(prevProps) {
      // 组件更新时也再检查一遍认证状态
      if (!condition(this.props)) {
        this.props.history.push('/login');
      }
    }

    render() {
      // 认证通过才渲染原组件,并且把所有props传过去
      return condition(this.props) ? <Component {...this.props} /> : null;
    }
  }

  // 必须用withRouter包裹,不然拿不到路由相关的props
  return withRouter(WithAuthorization);
};

第二步:用compose正确组合两个高阶组件

重点来了!compose的顺序是从右到左执行,所以你要把connect放在最右边(最后执行),这样它才能拿到react-router给的ownProps(包括match对象),然后withAuthorization放在左边(先执行)负责做认证保护。

直接上代码示例:

import { compose } from 'recompose';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import withAuthorization from './your-path-to/withAuthorization';
import UserDetails from './UserDetails';

// 定义你的认证条件,比如检查redux里有没有登录用户
const isAuthenticated = (props) => !!props.authUser;

const mapStateToProps = ({ users, auth }, ownProps) => {
  // 这里依然能像之前一样拿到uid参数
  return {
    user: users[ownProps.match.params.uid],
    authUser: auth.user // 把登录用户状态也取出来,给认证条件用
  };
};

// 组合顺序:connect先执行,然后withAuthorization
const UserDetailsWithAuth = compose(
  withAuthorization(isAuthenticated),
  connect(mapStateToProps)
)(UserDetails);

export default UserDetailsWithAuth;

第三步:在路由里用这个容器组件

最后在你的路由配置里,直接用这个带认证的容器组件就行:

import { Route } from 'react-router-dom';
import UserDetailsWithAuth from './UserDetailsWithAuth';

// 路由配置
<Route path="/user/:uid" component={UserDetailsWithAuth} />

为啥这样就行?

简单说,compose(A, B)(Component)就等于A(B(Component)),所以先让connect把redux状态和路由的ownProps合并好,再传给withAuthorization做认证检查,这样两边的功能都不耽误——既拿到了URL参数,又完成了路由保护。要是你把顺序反过来,connect就拿不到路由的match对象了,自然就获取不到uid参数了。

要是你想在认证条件里直接用redux的状态,上面的写法也能满足,因为connect已经把authUser传到props里了,withAuthorization的条件函数直接就能用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:26:06