5

React router用hooks读取routeName、根据routeName跳转

 3 years ago
source link: https://www.daozhao.com/10016.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

React router用hooks读取routeName、根据routeName跳转

如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!

React router用hooks读取routeName、根据routeName跳转

在迁移Vue至React的过程中遇到了一些路由相关的问题,在Vue项目中经常会使用routeName,毕竟使用path太长了,也记不住,我自己看了看React router也没有发现routeName相关的信息,可能是我没有找到,或者React没有这个概念吧。

在Vue中这样的写法比较常见

const router = new Router({
  routes: [{
      path: '/smart-mail',
      name: 'SmartMailBox',
      redirect: '/smart-mail/no-mail',
      component: SmartMailBox,
      children: [{
          path: 'new/:ts',
          name: 'MailNew',
          component: smartMailNew,
        },
        {
          path: 'info',
          name: 'MailDetail',
          component: smartMailInfo,
          children: [{
              path: 'view/:uid/:ts',
              name: 'MailView',
              component: smartMailView,
            },
            {
              path: 'reply/:uid/:ts',
              name: 'MailReply',
              component: smartMailReply,
            },
            {
              path: 'reply-all/:uid/:ts',
              name: 'MailReplyAll',
              component: smartMailReply,
            },
            {
              path: 'forward/:uid/:ts',
              name: 'MailForward',
              component: smartMailReply,
            },
            {
              path: 'draft/:uid/:ts',
              name: 'ReplyOrForwardDraft',
              component: smartMailReply,
            },
            {
              path: 'empty/:uid/:ts',
              name: 'MailEmpty',
              component: smartMailEmpty,
            },
            {
              path: 'new-draft/:uid/:ts',
              name: 'MailDraft',
              component: smartMailNew,
            },
          ],
        },
      ],
    },
  ],
});

需要跳转就使用routeName,避免长长的path

this.$router.push({
    name: 'MailView',
    params: {
       uid:  'xxx',
    }
})

file 迁移到React时可以这样做

// routes.js
export default [
  {
    path: "/smart-mail/no-mail",
    component: NoMail
  },
  {
    path: "/smart-mail/new/:ts",
    component: MailNew,
    routeName: 'MailNew'
  },
  {
    path: "/smart-mail/info/:uid",
    component: MailDetail,
    routes: [
      {
        path: "/smart-mail/info/:uid/view/:ts/:keyword?",
        component: MailView,
        routeName: 'MailView',
        exact: false,
      },
      {
        path: "/smart-mail/info/:uid/reply/:ts",
        component: MailReply,
        routeName: 'MailReply',
      },
      {
        path: "/smart-mail/info/:uid/replyAll/:ts",
        component: MailReply,
        routeName: 'MailReplyAll',

      },
      {
        path: "/smart-mail/info/:uid/forward/:ts",
        component: MailReply,
        routeName: 'MailForward',

      },
      {
        path: "/smart-mail/info/:uid/draft/:ts",
        component: MailReply,
        routeName: 'ReplyOrForwardDraft',

      },
      {
        path: "/smart-mail/info/:uid/empty/:ts",
        component: MailEmpty,
        routeName: 'MailEmpty',

      },
      {
        path: "/smart-mail/info/:uid/new-draft/:ts",
        component: MailNew,
        routeName: 'MailDraft',
      },
    ]
  },
];

上面的routeName是我们为了自己使用而额外增加的字段,我们可以自己写hook来实现根据routeName跳转了

// hook.js
import React from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import routes from "../../routes";

export function useReactRouter() {
  function findRoute(routes, routeName) {
    for (let item of routes) {
      if (item.routeName === routeName) {
        return item;
      } else if (item.routes){
        const result = findRoute(item.routes, routeName);
        if (result) {
          return result;
        }
      }
    }
  }

  function findRouteName(routes, pathName) {
    for (let item of routes) {
      if (item.routes) {
        return findRouteName(item.routes, pathName);
      } else {
        const staticPath = item.path.replace(/\/:\w+\??/g, '');
        const isMatch = pathName.indexOf(staticPath) === 0; // 判断是否当前pathName前部分是否与路由的静态地址前部分匹配
        if (isMatch) {
          return item.routeName;
        }
      }
    }
  }

  const history = useHistory();

  function historyPush(routeName, mailId, keyword = '') {
    const route = findRoute(routes, routeName);
    if (route) {
      const path = route.path.replace(':uid', mailId).replace(':ts', Date.now()).replace(':keyword', keyword);
      history.push(path);
    } else {
      throw new Error(`${routeName} not found`)
    }
  }
  const location = useLocation();

  const routeName = useMemo(() => {
    return findRouteName(routes, location.pathname);
  }, [location, routes]);

  return [routeName, historyPush, history];
}
获取routeName
  const [routeName] = useReactRouter();

根据当前路由的pathname在自己的静态路由表里面进行匹配,在匹配过程中有部分是动态参数,所以我们在定义路由的时候尽量将path里面的静态部分写在前面,方便匹配,需要注意前面匹配值的唯一性。

根据routeName跳转
  const [routeName, historyPush] = useReactRouter();
  historyPush.push('MailView', 'xxx');

这个有点类似上面过程的逆过程--根据routeName找到path,然后将传递的参数替换掉动态参数部分。

这样我们就可以类似Vue的方式来进行路由跳转了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK