withRouter的原理和用法

2,910 阅读2分钟

哈喽~我是刘十一,在了解withRouter之前我们先看看高阶组件吧。

什么是HOC

高阶组件(Higher-Ordercomponents)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。

具体而言,高阶组件是参数为组件,返回值为新组件的函数。

const EnhancedComponent = higherOrderComponent(WrappedComponent);

HOC的特点

  • 是 React 中用于复用组件逻辑的一种高级技巧
  • 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式(一种组件的设计模式)
  • 接受一个组件和额外的参数(如果需要),返回一个新的组件
  • 纯函数,没有副作用

HOC的优缺点

  • 优点∶ 逻辑复用、不影响被包裹组件的内部逻辑。
  • 缺点∶ HOC传递给被包裹组件的props容易和被包裹后的组件重名,进而被覆盖

HOC的应用场景

  • 代码复用,逻辑抽象
  • 渲染劫持
  • state 抽象和更改
  • props 更改

withRouter作用

withRouter是一个高阶组件中(HOC), 其作用是将一个组件包裹进Route里面, 然后react-router的三个对象history, location, match就会被放进这个组件的props属性中,此时这个组件就具备了路由的属性。

应用场景

所以withRouter的应用场景就是, 当我们某个东西不是一个Router, 但是我们要依靠它去跳转一个页面, 比如点击页面的logo, 返回首页, 这时候就可以使用withRouter来完成。即,解决方法是将span使用withRouter作为一个可点击跳转的Link。

使用withRouter

比如app.js这个组件,一般是首页,不是通过路由跳转过来的,而是直接从浏览器中输入地址打开的,如果不使用withRouter此组件的this.props为空,没法执行props中的history、location、match等方法。

如何应用于项目中

import * as React from 'react'
import { withRouter } from 'react-router-dom'

const CustomerMessageSearchForm = (props: any) => {
    
  return (
      <div>
      ......
      </div>
  
  )
      
}
export default withRouter(CustomerMessageSearchForm)

1.避免更新受阻

// before
export default connect(mapStateToProps)(Something)

// after
import { withRouter } from 'react-router-dom'
export default withRouter(connect(mapStateToProps)(Something))

因为react-redux的connect高阶组件会为传入的参数组件实现shouldComponentUpdate 这个钩子函数, 导致只有prop发生变化时才触发更新相关的生命周期函数(含render)而很显然,我们的location对象并没有作为prop传入该参数组件。

2.在组件中意图使用history来控制路由跳转

import React from "react";
import {withRouter} from "react-router-dom";

class MyComponent extends React.Component {
  ...
  myFunction() {
    this.props.history.push("/some/Path");
  }
  ...
}
export default withRouter(MyComponent);

如果我们不使用withRouter来处理(MyComponent),那么我们这里的this.props就取不到history,会报hitstory is undefiend之类的错。