首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >v6历史推送和useNavigate问题

v6历史推送和useNavigate问题
EN

Stack Overflow用户
提问于 2022-07-30 10:21:27
回答 3查看 1.5K关注 0票数 2

我在我的项目中使用了react路由器-dom v6和mobex,当我使用它时会得到一个错误,如下所示。

main.tsx:

代码语言:javascript
复制
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './app/layout/App'
import './app/layout/styles.css'
import 'semantic-ui-css/semantic.min.css'
import 'react-toastify/dist/ReactToastify.min.css'
import 'react-calendar/dist/Calendar.css'
import 'react-datepicker/dist/react-datepicker.css'
import { store, StoreContext } from './app/stores/store'
import { BrowserRouter } from 'react-router-dom'
import { useNavigate } from 'react-router-dom';
export const navigate = useNavigate();

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <StoreContext.Provider value={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </StoreContext.Provider>
  </React.StrictMode>
)

userStore.ts:

代码语言:javascript
复制
import { UserFormValues } from './../models/user';
import { makeAutoObservable, runInAction } from "mobx";
import { User } from "../models/user";
import agent from '../api/agent';
import { store } from './store';
import { navigate } from '../../main';

export default class UserStore {
    user:User | null = null;

    constructor() {
        makeAutoObservable(this);
    }

    logout = () => {
        store.commonStore.setToken(null);
        window.localStorage.removeItem('jwt');
        this.user = null;
        navigate('/');
    }
}

错误:

代码语言:javascript
复制
"Invalid hook call. Hooks can only be called inside the body of a function component"

在旧版本中,当我这样做时,它正在工作:

main.tsx:

代码语言:javascript
复制
...
...
import { createBrowserHistory } from "history";
export const history = createBrowserHistory();
...
...

和userStore.tsx:

代码语言:javascript
复制
import { makeAutoObservable, runInAction } from "mobx";
import agent from "../api/agent";
import { User, UserFormValues } from "../models/user";
import { store } from "./store";
import { history } from "../../index";

export default class UserStore {
  user: User | null = null;

  constructor() {
    makeAutoObservable(this);
  }

  logout = () => {
    store.commonStore.setToken(null);
    window.localStorage.removeItem("jwt");
    this.user = null;
    history.push("/");
  };

我该如何解决这个问题?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-07-30 10:53:27

这一行const navigate = useNavigate()只能在一个React组件或自定义钩子中,因为useNavigate是一个钩子。见钩子规则了解更多。解决这一问题的一种方法是更改logout函数,以便将navigate作为参数,如下所示:

代码语言:javascript
复制
logout = (navigate) => {
  store.commonStore.setToken(null);
  window.localStorage.removeItem("jwt");
  this.user = null;
  navigate("/");
};

并在组件中调用useNavigate,调用logout并将navigate作为参数提供给它。就像这样,例如:

代码语言:javascript
复制
import UserStore from "./UserStore"; // use the correct path
import { useNavigate } from "react-router-dom";

export default function Component() {
  const navigate = useNavigate();
  const userStore = UserStore();
  userStore.logout(navigate);

  return <div></div>;
}
票数 2
EN

Stack Overflow用户

发布于 2022-07-30 21:33:56

问题

React钩子只能在React函数组件中使用,而useNavigate钩子只能在路由上下文中使用。

解决方案

通过React函数组件通过navigate钩子访问useNavigate函数,并将对navigate的引用传递给logout处理程序。

代码语言:javascript
复制
logout = ({ navigate }) => {
  store.commonStore.setToken(null);
  window.localStorage.removeItem("jwt");
  this.user = null;
  navigate("/");
};

..。

代码语言:javascript
复制
const SomeComponent = () => {
  const navigate = useNavigate();

  ...
  UserStore.logout({ navigate });
  ...
};

替代解

导入和使用HistoryRouter,并像以前一样继续使用自定义history对象。这需要history@5包依赖关系,必要时安装它(运行npm i -S history@5)。

示例:

创建并导出history对象。

代码语言:javascript
复制
import { createBrowserHistory } from "history";
export const history = createBrowserHistory();

..。

代码语言:javascript
复制
...
import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom';
import { history } from '../path/to/history';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <StoreContext.Provider value={store}>
      <HistoryRouter history={history}>
        <App />
      </HistoryRouter>
    </StoreContext.Provider>
  </React.StrictMode>
);

UserStore继续导入并使用history对象。

代码语言:javascript
复制
import { makeAutoObservable, runInAction } from "mobx";
import agent from "../api/agent";
import { User, UserFormValues } from "../models/user";
import { store } from "./store";
import { history } from "../path/to/history";

export default class UserStore {
  user: User | null = null;

  constructor() {
    makeAutoObservable(this);
  }

  logout = () => {
    store.commonStore.setToken(null);
    window.localStorage.removeItem("jwt");
    this.user = null;
    history.push("/");
  };

  ...
票数 1
EN

Stack Overflow用户

发布于 2022-07-30 10:35:48

不能在类组件中使用钩子。对于路由槽类组件,还有另一种方法。但我认为在路由器6类组件支持被取消。因此,您可以将类组件更改为函数组件--这是一种简单的方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73174746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档