# withRouter 封装

  这里先对自己编写的高阶组件withRouter做一个汇总,方便查阅:

import { useNavigatge, useParams, useSearchParams } from 'react-router-dom'

function withRouter(WrapperComponent) {
  return function (props) {
    // 1、路由跳转
    const navigate = useNavigatge()
    // 2、路径参数
    const params = useParams()
    // 3、查询参数
    const [searchParams] = useSearchParams()
    const query = Object.fromEntries(searchParams) // 转换为普通对象

    const router = { navigate, params, query }

    return <WrapperComponent {...this.props} router={router} />
  }
}

export default withRouter

# 1、API 导航

  若我们使用的是函数式组件,那我们可以直接使用其提供的 hooks:useNavigatge

useNavigatge 使用示例
  • 可传参数
interface NavigateFunction {
  (to: To, options?: { replace?: boolean; state?: any }): void
  (delta: number): void
}
  • 使用示例
import { useNavigatge } from 'react-router-dom'

function Demo(props) {
  const navigate = useNavigatge()

  function navigateTo(path) {
    navigate(path)
  }

  // 记得要在App.jsx中写上映射关系
  return <button onClick={(e) => navigateTo('/category')}>分类</button>
}

  那在类组件中,我们该如何操作呢?

答案

  既然类组件中无法使用 useNavigatge,那我们自己封装一个高阶组件算了 🤔

核心: 高阶组件 + react-router@5 中的withRouter (opens new window)

  • 封装
import { useNavigatge } from 'react-router-dom'

function withRouter(WrapperComponent) {
  return function (props) {
    const navigate = useNavigatge()
    const router = { navigate }

    return <WrapperComponent {...this.props} router={router} />
  }
}

export default withRouter
  • 使用
class Demo extends React.PureComponent {
  navigateTo(path) {
    // 使用🚩
    const { navigate } = this.props.router

    navigate(path)
  }

  render() {
    // 记得要在App.jsx中写上映射关系
    return <button onClick={(e) => this.navigateTo('/category')}>分类</button>
  }
}

export default withRouter(Demo)

# 2、路径参数

  若我们使用的是函数式组件,那我们可以直接使用其提供的 hooks:useParams

  同样的在类组件中是无法使用的,需要我们封装高阶组件

  • 封装
import { useParams } from 'react-router-dom'

function withRouter(WrapperComponent) {
  return function (props) {
    const params = useParams()
    const router = { params }

    return <WrapperComponent {...this.props} router={router} />
  }
}

export default withRouter
  • 使用
class Demo extends React.PureComponent {
  navigateToDetails(id) {
    // 使用🚩
    const { navigate } = this.props.router

    navigate('/category/' + id)
  }

  render() {
    return (
      <ul>
        <li onClick={(e) => this.navigateToDetails(category.id)}>分类</li>
      </ul>
    )
  }
}

export default withRouter(Demo)
class Category extends React.PureComponent {
  render() {
    const { params } = this.props.router

    return (
      <div>
        <p>id: {params.id}</p>
      </div>
    )
  }
}

export default withRouter(Category)

# 3、查询参数

  若我们使用的是函数式组件,那我们可以直接使用其提供的 hooks:useLocation

  同样的在类组件中是无法使用的,需要我们封装高阶组件

  • 封装
import { useLocation, useSearchParams } from 'react-router-dom'

function withRouter(WrapperComponent) {
  return function (props) {
    // 方式1
    const location = useLocation()
    // 方式2
    const [searchParams] = useSearchParams()
    const query = Object.fromEntries(searchParams) // 转换为普通对象

    const router = { location, query }

    return <WrapperComponent {...this.props} router={router} />
  }
}

export default withRouter
  • 使用
class Demo extends React.PureComponent {
  navigateToDetails(path) {
    // 使用🚩
    const { navigate } = this.props.router

    navigate(path)
  }

  render() {
    return (
      <ul>
        <li onClick={(e) => this.navigateToDetails(`/category?id=${category.id}`)}>分类</li>
      </ul>
    )
  }
}

export default withRouter(Demo)
class Category extends React.PureComponent {
  render() {
    const { location, query } = this.props.router

    return (
      <div>
        <p>id: {location.search}</p>
        <p>id: {query.id}</p>
      </div>
    )
  }
}

export default withRouter(Category)
更新于 : 7/8/2024, 10:21:14 AM