ReactRouter进阶技巧

简介: ReactRouter进阶技巧

在编写react项目中的时候,常常会用到react-router这个插件来满足项目的需求。这个插件用法起来确实别vue路由用法稍微麻烦了一些,但是只有我们配置好,也能在项目中应用得当。
有时候会需要使用编程式导航,比如上方导航栏里面选项,响应按钮事件,进行路由跳转。react 的做法是通过高阶函数,函数体内部向组件的 props 注册一些路由的方法,最后返回一个新的组件。

下面是一个结合 TypeScript 使用 withRouter 的例子:

interface NavigationState {
  routes: Array<{
    path: string;
    name: string;
    key: string;
  }>;
  selectedKey: string;
}

interface NavigationProps {
  name: string;
}

class Navigation extends Component<
  RouteComponentProps & NavigationProps, // 使用「交叉类型」来处理Props的关系
  NavigationState
> {
  state = {
    routes: [],
    selectedKey: "1"
  };

  toggleRoute = (event: ClickParam) => {
    this.props.history.push(path); // route的方法已经被注册到了Props上
  };

  render() {
     // ...
    );
  }
}

export default withRouter(Navigation);

严格匹配: exact 和 strict

exact已经关闭了模糊匹配。那么strict设置为true(默认是false),会有什么区别呢。例如 path 为 /a的时候:

  • 两个 prop 均为true:不匹配/a/,只匹配/a
  • strict 为 false:/a//a均匹配

路由配置化

可以直接使用 react-router-config 组件,实现原理:

import { Route, Switch, SwitchProps, RouteProps } from "react-router-dom";

function renderRoutes(params: {
  routes: RouteProps[];
  switchProps?: SwitchProps;
}) {
  const { switchProps, routes } = params;
  return (
    <Switch {...switchProps}>
      {routes.map((route, index) => (
        <Route
          key={index}
          path={route.path}
          component={route.component}
          exact={route.exact || true}
          strict={route.strict || false}
        ></Route>
      ))}
    </Switch>
  );
}

假设我们的路由如下:

import { RouteProps } from "react-router-dom";

const config: RouteProps[] = [
  {
    path: "/",
    component: HomePage
  },
  {
    path: "/user",
    component: UserPage
  }
];

路由变化响应

在 VueJS 技术栈中,vue-router 是提供路由响应的钩子函数,例如:beforeEachafterEach等等。

但是在 React 中,react-router 并不提供相关的钩子函数。那么如果有顶部导航栏,不同页面切换时,高亮不同的标签,那么应该怎么实现响应路由变化呢

首先即使是路由,在 React 中,它也是一个组件对象。因此,如果要更新试图,必须触发组件的 render。而触发组件的关键在于,props 发生改变。

第一步:需要使用withRouter来包装对应的组件,将路由的信息作为 props 注入组件,比如顶部导航栏。

第二步:下面是 React17 前后的简单例子。

React17 之前:

import { withRouter, RouteComponentProps } from "react-router-dom";

class Navigation extends Component<RouteComponentProps, any> {
  state = {
    selectedPath: "/"
  };

  // 在componentWillReceiveProps中接受新的props
  // 决定是否更新state
  componentWillReceiveProps(nextProps: RouteComponentProps) {
    if (nextProps.location.pathname === this.props.location.pathname) {
      this.setState({ selectedPath: nextProps.location.pathname });
    }
  }

  render() {
    // 这里的render渲染,取决于state是否更新
    const { selectedPath } = this.state;
    return <div>导航栏选中信息:{selectedPath}</div>;
  }
}

export default withRouter(Navigation);

在 React17 之后,不推荐使用componentWillReceiveProps等不确定的生命周期。处理的思路是:render 函数返回的视图中,变量的变化依赖 props 属性的值。

import { withRouter, RouteComponentProps } from "react-router-dom";

class Navigation extends Component<RouteComponentProps, any> {
  state = {
    paths: ["/", "/a"]
  };

  render() {
    const { pathname } = this.props.location;
    const { paths } = this.state;

    let selectedPath = "";
    paths.some(path => {
      if (path === pathname) {
        selectedPath = path;
        return true;
      }
      return false;
    });

    return <div>导航栏选中信息:{selectedPath}</div>;
  }
}

export default withRouter(Navigation);
相关文章
|
10天前
|
人工智能 数据挖掘 开发者
探索Python编程:从基础到进阶
【10月更文挑战第32天】本文旨在通过浅显易懂的语言,带领读者从零开始学习Python编程。我们将一起探索Python的基础语法,了解如何编写简单的程序,并逐步深入到更复杂的编程概念。文章将通过实际的代码示例,帮助读者加深理解,并在结尾处提供练习题以巩固所学知识。无论你是编程新手还是希望提升编程技能的开发者,这篇文章都将为你的学习之旅提供宝贵的指导和启发。
|
1月前
|
定位技术 API Apache
|
1月前
|
Oracle Java 关系型数据库
Java编程之旅:从基础到进阶
Java,一种广泛使用的编程语言,因其平台无关性、面向对象的特性而备受推崇。本文旨在通过简明易懂的语言和实际代码示例,引导初学者了解Java的基本概念,并逐步深入到更复杂的编程技巧。我们将从Java的安装开始,经过变量、数据类型、控制结构等基础知识的学习,最后探讨异常处理和文件操作等进阶话题。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你提供有价值的参考和启示。
|
1月前
|
程序员 数据库 开发者
探索Python编程之旅:从基础到进阶
【9月更文挑战第34天】本文将引导你踏上Python编程的奇妙旅程,从最初的安装和运行第一个程序开始,逐步深入到面向对象编程、文件操作和网络编程等高级主题。我们将通过代码示例和清晰的步骤解释,帮助你构建起对Python语言的深刻理解,并鼓励你在遇到问题时主动寻找解决方案,培养解决问题的能力。无论你是初学者还是有一定经验的开发者,都能在这篇文章中找到有价值的内容和启发。
|
2月前
|
人工智能 数据挖掘 开发者
Python编程:从基础到进阶
【8月更文挑战第59天】本文将带你进入Python的世界,从基础语法到进阶技巧,让你轻松掌握Python编程。我们将通过实例讲解,让你在实际操作中提升技能。无论你是初学者还是有一定基础的开发者,都能在本文中找到适合自己的学习内容。让我们一起探索Python的魅力吧!
|
2月前
|
机器学习/深度学习 存储 人工智能
探索Python编程的魔法:从基础到进阶
【9月更文挑战第16天】本文将带领你进入Python编程的世界,无论你是初学者还是有一定经验的开发者。我们将一起揭开Python编程的神秘面纱,通过实际案例和代码示例,深入浅出地探讨Python的基础语法、数据结构、面向对象编程以及函数式编程等核心概念。文章旨在提供一条清晰的学习路径,帮助你构建坚实的编程基础,并逐步过渡到更高级的编程技巧。无论你的目标是数据分析、网络开发还是机器学习,这篇文章都将为你打下扎实的基础,让你在编程的道路上越走越远。
21 6
|
3月前
|
数据采集 存储 人工智能
掌握Python编程:从基础到进阶的实用指南
【8月更文挑战第17天】 本文旨在通过浅显易懂的语言和实际案例,为初学者和有一定基础的开发者提供一条清晰的Python学习路径。我们将从Python的基本语法入手,逐步深入到面向对象编程、数据科学应用及网络爬虫开发等高级主题。每个部分都配备了代码示例和实操建议,确保读者能够将理论知识转化为实际能力。无论你是编程新手,还是希望提升Python技能的开发者,这篇文章都将为你打开一扇通往高效编程世界的大门。
28 2
|
5月前
|
编译器 C++
C++模板进阶
C++模板进阶
24 1
|
5月前
|
存储 算法 开发者
掌握Python编程:从基础到进阶
【6月更文挑战第7天】本文将引导读者了解并掌握Python编程语言的基础知识和进阶技巧。我们将从Python的基本语法开始,逐步深入到更复杂的主题,如数据结构和算法、面向对象编程以及网络编程。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。
|
6月前
|
存储 安全 编译器
【C++进阶】C++11入门基础
【C++进阶】C++11入门基础
40 0