如何在userStore类中调用LoginForm组件的navigate路由方法
可行实现方案
useNavigate 是 React Router 提供的 Hook,仅能在函数组件、自定义Hook内部调用,类组件、MobX Store 这类普通JS/TS类环境下无法直接使用。以下是两种可落地的实现方式,按推荐优先级排序:
方案1:路由逻辑放回组件层处理(优先选择,耦合度最低)
Store 只负责处理登录请求、维护用户状态,路由跳转这类和视图层强绑定的逻辑放回组件层实现,完全不需要改动Store的核心逻辑,可维护性最高。
你现有的userStore.login本身就是async函数,会返回Promise,只需要修改LoginForm里的提交方法即可:
// LoginForm 组件内的 handleSubmit 修改为 async 形式 async function handleSubmit() { try { await userStore.login(info); // 登录成功后执行跳转 navigate('/restaurant'); } catch (error) { setError('Invalid Email or Password'); } }
修改后直接删除UserStore里注释的this.props.navigate相关代码即可,Store不需要感知任何路由逻辑,后续调整跳转规则也只需要改组件代码,单测也更方便。
方案2:封装全局路由实例(适合非组件层统一调用的场景)
如果项目里有大量在Store、工具函数中触发路由跳转的需求,可以封装全局可调用的路由实例,脱离Hook限制使用。
- 安装history依赖:
npm i history - 新建全局history工具文件:
// src/utils/history.ts import { createBrowserHistory } from 'history'; export default createBrowserHistory(); - 替换项目根节点的路由组件,传入自定义history实例:
// 项目入口文件(main.tsx/App.tsx) import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom'; import history from './utils/history'; ReactDOM.createRoot(document.getElementById('root')!).render( <HistoryRouter history={history}> <App /> </HistoryRouter> ) - 在UserStore中直接引入history实例即可实现跳转:
// UserStore 内 import history from '../../utils/history'; login = async (creds: UserFormValues) => { try { const user = await agent.Account.login(creds); store.commonStore.setToken(user.token); runInAction(() => this.user = user); // 直接调用push方法跳转 history.push('/restaurant'); console.log(user); } catch (error) { throw error; } }
不推荐写法
不要把组件中获取到的navigate函数作为参数传入Store的login方法(比如userStore.login(info, navigate)),这种写法会让Store和路由逻辑强耦合,后续其他位置调用login方法时都需要额外传入navigate参数,维护成本很高。
内容的提问来源于stack exchange,提问作者Dren Ibrahimi
相关产品推荐
相关产品推荐

