Make writing a habit together! This is my first day to participate in the “Gold Digging Day New Plan · April More text challenge”, click to see the details of the activity.

Here’s the first thing

A friend of mine hasn’t been developing the react front end for a long time, so some simple features and pages are fine. Not long ago React 18 was released, he created a new project using create-React app to practice his skills. However, he encountered a lot of problems, so he asked me to help him. This led to some seemingly simple but frustrating problems for beginners.

reactIt’s 18, but why is it stillReactDom.render?

Create-react-app creates a new project with reactdom. render as follows:

import React from 'react'
import ReactDOM from 'react-dom' ----------react 17 uses ReactDOM
import App from './App'
import './index.css'

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>.document.getElementById('root'))Copy the code

ReactDOM uses the render function to render JSX Elements onto a DOM node with id ‘root’.

So let’s write react 18 in a new way

The react 18 changed

//index.tsx
import React from 'react'
import { createRoot } from 'react-dom/client' // ---------- React 18 uses createRoot in ReactDOM/client
import App from './App'
import './index.css'

function render() {
  const root = createRoot(document.getElementById('root')! root.render(<React.StrictMode>
      <App />
    </React.StrictMode>)}Copy the code

React-dom /client uses the createRoot function to Render the JSX Elements as a renderer.

React router v6 react router v6 react router v6

React-router V6 is a new version of routing-to-router v6.

React-router v5

//app.tsx
import React from 'react'
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
export default() = > {return (
      <Router>
        <Switch>
          <Route path="/" component={Login} />
          <Route path="/pageCenter" component={PageCenter} />
        </Switch>
      </Router>)})Copy the code

The PageCenter is our page component, and we typically implement nested routines here, such as:

//PageCenter.tsx
import React from 'react'
import { Route, Switch } from "react-router-dom";
export default() = > {return (
      <>
        <Switch>
          <Route path="/" component={Login} />
          <Route path="/pageCenter" component={PageCenter} />
        </Switch>
      <>)})Copy the code

Em ~ ~ ~, which is similar to the top-level routing implemented in app.tsx.

Evaluate the organization of a wave OF V5 routes

  • tsxFile bloated: Write a route for each route configuredRouteComponents that I personally don’t like, I don’t want minetsxToo much code, which is my preference, for easy and clear reading.
  • The project folder structure is complex and nested:The top-level and nested subroutes are configured separately, which directly affects the arrangement of folder structure in engineering projects. Because it is not possible to clarify the organizational relationship between page components directly, it will be very confusing and difficult to maintain, so it falls on to clarify the relationshipThe folder structure of the projectBy design, that would lead toThe folder structure of the projectAs theOrganization mode of V5 routesComplex and complex.

React-router v6

There are probably a number of reasons why V6 has changed so much, most notably:

  • V6 introduces configuration routing: a simple configuration object that fully describes the appearance and organization of routing.
  • Simple route nesting: just use the newly launched tag in the component with nested routines. Elegant.

However, there were some disruptive changes that caught me off guard, like:

  • Route interception is gone!! : Intercept ah, but, why not, this…
  • withRouterNo more!!I can use the function componenthookWhat about class components? This is…

Em ~ ~ ~ nothing repect, after all progress, how can there be no cost, there is no za to make their own, do not take a car will not go?

I wrote a library called R6Helper to compensate for the v6 upgrade as much as possible

  • Intercept, arranged.
  • withRouterThe arrangement is made.

Route good, then route lazy load, how to do?

The react. lazy import is introduced dynamically.

const Login = React.lazy(() = > import('./login'))
Copy the code

In Suspense, use react. Suspense to wrap this lazy component, otherwise you will get an error. My friend is stuck with this for a long time. In Suspense because you forgot to wrap a layer around lazy loading components.

<React.Suspense fallback={<>.</>} > {<Login />}</React.Suspense>
Copy the code

But my friend tells me to write lazy components and Suspense packages for every page you add, so your code will look like this:

const Login = React.lazy(() = > import('./pages/login'))
const Page1 = React.lazy(() = > import('./pages/page1'))
const Page2 = React.lazy(() = > import('./pages/page2'))
const Page3 = React.lazy(() = > import('./pages/page3'))
const Page4 = React.lazy(() = > import('./pages/page4'))
const Page5 = React.lazy(() = > import('./pages/page5'))...export default() = > {return useRoutes([
    {
      path: '/'.element: <React.Suspense fallback={<>.</>} > {<Login />}</React.Suspense>
    },
    {
      path: '/page1'.element:<React.Suspense fallback={<>.</>} > {<Page1 />}</React.Suspense>
    },
    {
      path: '/page2'.element: <React.Suspense fallback={<>.</>} > {<Page2 />}</React.Suspense>
    },
    {
      path: '/page3'.element: <React.Suspense fallback={<>.</>} > {<Page3 />}</React.Suspense>
    },
    {
      path: '/page4'.element: <React.Suspense fallback={<>.</>} > {<Page4 />}</React.Suspense>
    },
    {
      path: '/page5'.element: <React.Suspense fallback={<>.</>} > {<Page5 />}</React.Suspense>
    },
    {
      path: '/ 404'.element: <div>not found</div>}},])Copy the code

This looks very redundant, a lot of repeated code, I hope I can help him optimize, em ~ ~ ~ no problem, open the whole.

Optimize the code

Mainly from two aspects:

  • componentlazyThe introduction of the
  • thenSuspenseOn the parcel

Unified entrance

First of all, page components were placed in the Pages path, and then directed to import. We added an index in the Pages folder for unified management.

// File: pages/index.ts
export Login = React.lazy(() = > import('./pages/login'))
export Page1 = React.lazy(() = > import('./pages/page1'))
export Page2 = React.lazy(() = > import('./pages/page2'))
export Page3 = React.lazy(() = > import('./pages/page3'))
export Page4 = React.lazy(() = > import('./pages/page4'))
export Page5 = React.lazy(() = > import('./pages/page5'))
Copy the code

Then let’s refactor the introduced code:

const { Login, Page1, Page2, Page3, Page4, Page5 } from './pages'
Copy the code

Encapsulate packaging components, supporting multiple types

Write a component that can wrap multiple types of components, all of which can be wrapped:

  • Components, including: function components and class components.
  • Lazy components.
  • JSX element.

The code is as follows:

// Loading an asynchronous component
export const wrapper = (Child: any, cutonFallBack? : CutonFallBackT) = > {
  / / determine JSX
  if(Child.type && ! Child._init && ! Child._payload) {return Child
  } else {
    // Check whether it is clAS and function components
    if (typeof Child === 'function') {
      return <Child></Child>
    } else {
      // Determine whether the component is lazy
      return (
        <React.Suspense fallback={cutonFallBack || <>.</>} > {<Child></Child>}
        </React.Suspense>
      )
    }
  }
}
Copy the code

So this whole refactored code is going to look something like this

const { Login, Page1, Page2, Page3, Page4, Page5 } from './pages'.export default() = > {return useRoutes([
    {
      path: '/'.element: wrapper(Login)
    },
    {
      path: '/page1'.element: wrapper(Page1)
    },
    {
      path: '/page2'.element: wrapper(Page2)
    },
    {
      path: '/page3'.element: wrapper(Page3)
    },
    {
      path: '/page4'.element: wrapper(Page4)
    },
    {
      path: '/page5'.element: wrapper(Page5)
    },
    {
      path: '/ 404'.element: wrapper(<div>not found</div>)})}Copy the code

Em ~ ~ ~ plain, but the code looks comfortable, friends sigh learned a lot of dry goods, I feel this is the basic operation, 233333.