道招

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/view/:uid/:ts/:keyword?",
        component: MailView,
        routeName: 'MailView',
        exact: false,
      },
      {
        path: "/smart-mail/info/reply/:uid/:ts",
        component: MailReply,
        routeName: 'MailReply',
      },
      {
        path: "/smart-mail/info/replyAll/:uid/:ts",
        component: MailReply,
        routeName: 'MailReplyAll',

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

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

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

      },
      {
        path: "/smart-mail/info/new-draft/:uid/: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的方式来进行路由跳转了。

更新时间:
上一篇:下一篇:

相关文章

关注道招网公众帐号
道招开发者二群