The react-Router API has been used for a long time. The react-Router API has been used for a long time. This article will implement a simple version of the React – Router

Design ideas

 As you can see from the figure above, the core content is how to listen for URL changes? There are only two ways to pushstate and pushstateBrowser forward and back. Refresh the page at the current URL, no URL changes involved. As mentioned in the last article, front-end routing works in two ways

  1. URL changes do not refresh the page.
  2. Listen for URL changes.

Therefore, when designing a React-router, you need to consider both pushstate and browser forward and backward URL changes.

Router

Function: Responsible for listening to the page object change and start rendering the page again **

  1. Define a context to pass history data to all child components
const RouteContext = React.createContext({})
Copy the code
  1. Define a Router component that listens for URL changes
const globalHistory = window.history // history Uses window global history
class Router extends React.Component {
  constructor(props) {
    super(props)
    this.state = { // Set location to state to update the page every time the URL changes
      location: window.location
    }
    // The popState event is triggered when the browser moves forward or backward
    window.addEventListener("popstate".() = > {
      this.setState({
        location: window.location
      })
    })
  }
  // The second jump is pushstate
	// Provide a push method to the child component to update the route and jump to the page
  push = (route) = > {
    globalHistory.pushState({}, "", route)
    this.setState({
      location: window.location
    })
  }
	// Define context to pass generic content to child components
  render() {
    const { children } = this.props
    const { location } = this.state
    return (
      <RouteContext.Provider value={{
        history: globalHistory.location.push: this.push,
      }}>
        {
          React.cloneElement(children, {
            history: globalHistory,
            location,
            push: this.push,
          })
        }
      </RouteContext.Provider>)}}export default Router
Copy the code

Route

Function: after the page starts rendering, according to the specific page location information to display the specific routing address corresponding content **

import React, { useContext } from 'react'
const Route = (props) = > {
  // Get the relevant information in the context
  const context = useContext(RouteContext)
  // Calculate the path that location matches
  const computedPath = (path, exact) = > {
    ...TODO 
    // This is the same as the source code, the core of which uses the path-to-regexp library to calculate the parameters in the URL
  }
  // eslint-disable-next-line no-unused-vars
  const { render, children, component, path, exact = false. rest } = propsconst match = computedPath(path, exact)
  constparams = { ... context, match,location: context.location }
  // Render is also the source of the ternary operation. Pass the associated attributes to the child component
  if (match) {
    if (children) {
      if (typeof children === 'function') {
        return children(params)
      }
      return React.cloneElement(children, params)
    } else if (component) {
      return component(params)
    } else if (render) {
      return render(params)
    }
  }
  return null
}

export default Route
Copy the code

This is a simple react-Router that can jump to and from a page.

Full code: [github.com/LiuSandy/we…