道招

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的方式来进行路由跳转了。

更新时间:
上一篇:邮箱收件人组件成长历程(三)跨栏拖拽不同数据方案对比下一篇:怎么调试Webpack+React项目,报错basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")怎么办

相关文章

vue多语言的解决方案不只是 vue-i18n,前端+后端完整解决方案

网上搜很多vue多语言的,一般都是介绍vue-i18n怎么使用,当然这是不错的,但是我们如果只是讲这个的话,只是解决了静态文字的多语言化。 这一部分我们也简单讲一下 npm install 阅读更多…

Vue和React hooks实现Select批量选择、选中条数、全选、反选实现对比

批量选择、全选、反选这些功能使用频率还是很高的,下面直接看看Vue和React分别怎么实现吧。 Vue 在使用Vue的时候是很容易实现的,我们以下列数据格式为例: const data 阅读更多…

改造富文本编辑器wangEditor成react组件

我们知道wangEditor常用的功能是editor实例的 txt.html() 和 txt.text() 方法,尤其是 txt.html() 方法,这是一个类似与jQuery常用的那种get和se 阅读更多…

怎么调试Webpack+React项目,报错basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")怎么办

今天在WebStorm上Windows上准备调试一个React项目,就出现了这样的报错。 Node Parameters里面写的是webpack-dev-server的执行文件 .\node_mod 阅读更多…

邮箱收件人组件(vue版)成长历程(一)

前期项目中需要优化原始的收件人、抄送、密送部分,换成更加现代化的样式和用户,当时将这部分抽象成一个组件了,最近的需求是发件人也要使用该组件,鉴于发件人比收件人等需要校验的地方和交互习惯变动点较多,进 阅读更多…

Vue在chrome44偶现点击子元素事件无法冒泡

公司的一个项目大致是这样的:一个左侧列表,点击左侧列表的文章标题,右侧展开该文章对应的内容的。 现在的问题出现在极少部分客户有时左侧的标题,无法打开对应的右侧的内容,给人的改进就是‘卡’、点不动、点 阅读更多…

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