私は友人がコードをリファクタリングするのを手伝いました、そして彼は彼をでたらめと呼びました、しかし彼は何もしませんでした

一緒に書く習慣を身につけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加した初日です。クリックしてイベントの詳細をご覧ください

まずはこれです

私の友人は、reactを使ってフロントエンドを長い間開発しておらず、いくつかの単純な関数やページは大きな問題ではありません。少し前Reactに18がリリースされ、彼はそれを使って手を一緒に練習する新しいプロジェクトをcreate-react-app作成しましたが、あらゆる種類の問題に遭遇した人は誰でも助けてください。次に話し合うことがいくつかあります。簡単に思えますが、正しいです。初心者がつまずくための小さな問題。

react私は18歳ですが、なぜReactDom.renderですか?

create-react-app新しく作成されたプロジェクトは、次のように引き続き使用さReactDom.renderれます。

import React from 'react'
import ReactDOM from 'react-dom' //《----------react 17使用的ReactDOM
import App from './App'
import './index.css'

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)
复制代码

一般的なセマンティクス:関数ReactDOMを使用して、コンポーネントを''でノードにレンダリングします。renderJSX Elementsidrootdom

次にreact 18、新しい書き込み方法を使用して変換します

react 18かわった

//index.tsx
import React from 'react'
import { createRoot } from 'react-dom/client' //《----------react 18使用的ReactDOM/client中的createRoot
import App from './App'
import './index.css'

function render() {
  const root = createRoot(document.getElementById('root')!)
  root.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  )
}
复制代码

セマンティクスは大まかに次のとおりです。関数react-dom/clientを使用して'' 'であるノードレンダラーにし、次に関数を使用してそれをレンダリングします。createRootidrootdomRenderJSX Elements

Reactは18で、React-routerにはv6がありますが、大きく変更されています。使用方法は?

React-router v6変化は小さくないと言えます。以前のv5組織ルーティングは次のようになります。

React-routerv5

//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>
    )
  }
)
复制代码

PageCenterこれは私たちのページコンポーネントであり、一般的にここに実装されています嵌套路由

//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>
      <>
    )
  }
)
复制代码

em ~~~~、app.tsxに実装されているトップレベルのルーティングと同じ行にあります。

v5ルーティングの波がどのように編成されているかを評価します

  • tsx 文件大臃肿:每配置一个路由,就写一个 Route 组件,我个人是不喜欢的,我不希望我的 tsx 的代码太多,这是我的喜好,为了阅读起来容易,清晰。
  • 项目的文件夹结构复杂嵌套:顶层路由和嵌套子路由配置分离,直接影响了工程项目中对项目的文件夹结构的编排。因为不能够很直接理清页面组件间的组织关系,不理清会很混乱,维护难度加大,所以理清关系就落在了项目的文件夹结构设计了,这就会导致项目的文件夹结构随着v5 路由的组织方式的复杂而复杂。

React-router v6

可能是因为 v5 的种种原因,才导致 v6 的变化那么大,最突出便是:

  • v6 痛快的推出了配置式路由:一个简单的配置对象,充分描述出了路由的样子和组织关系,痛快~~~。
  • 简洁的路由嵌套方式:仅仅在配置了嵌套路由组件中,使用新推出的标签就搞定了,优雅~~~。

不过~~~,也有一些破坏性的改变,让我措手不及,比如:

  • 路由拦截无了!!!:拦截啊可是,怎么没有了,这。。。
  • withRouter无了!!!:函数组件我能用hook搞搞,类组件咋办,这。。。

em ~~~没事 repect,毕竟进步嘛,怎么会没代价呢,没有咱就自己搞被,不坐车就不会走了么?

我为此写了一个库r6helper,尽可能的弥补了升级 v6 带来的影响

  • 拦截,安排上了。 ezgif.com-gif-maker.gif
  • withRouter,安排上了。

路由好了,那么路由懒加载得有吧,怎么搞?

方式还是依然是通过 React.lazy配合import的动态引入,代码如下。

const Login = React.lazy(() => import('./login'))
复制代码

次にReact.Suspense、この遅延読み込みコンポーネントをラップする必要があります。そうしないと、エラーが報告されます。私の友人は長い間立ち往生しています。、その理由は、レイジーコンポーネントの周りにレイヤーをラップするのを忘れたためですReact.Suspense

<React.Suspense fallback={<>...</>}>{<Login />}</React.Suspense>
复制代码

ただし、私の友人は、ページを追加するたびに、lazyインポートコンポーネントとSuspenseパッケージを作成し、さらにページが増えると、コードは次のようになると言っていました。

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>
    },
  ])
}
复制代码

これは非常に冗長に見えます。繰り返されるコードがたくさんあります。彼がそれを最適化するのを手伝ってくれることを願っています。em~~~問題ありません、全体を開いてください。

コードを最適化する

主に2つの側面から:

  • コンポーネントlazyのインポート
  • その後、Suspenseラップ

統一された入り口

まず、ページコンポーネントがpagesパスの下に配置され、次にインポートするように指示されます。統合管理のためindexに、フォルダーの下に1つ追加します。pages

// 文件: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'))
复制代码

次に、前のインポートコードをリファクタリングします。

const { Login, Page1, Page2, Page3, Page4, Page5 } from './pages'
复制代码

パッケージングコンポーネントをカプセル化し、複数のタイプをサポート

複数のタイプをラップできるコンポーネントを記述します。これらはすべてラップできます。

  • コンポーネントを含む:関数コンポーネントクラスコンポーネント。
  • 怠惰なコンポーネント
  • jsx要素

その場合、コードは次のようになります。

// 加载异步组件的loading
export const wrapper = (Child: any, cutonFallBack?: CutonFallBackT) => {
  // 判断jsx
  if (Child.type && !Child._init && !Child._payload) {
    return Child
  } else {
    // 判断是否为clas和function组件
    if (typeof Child === 'function') {
      return <Child></Child>
    } else {
      // 判断是否为lazy组件
      return (
        <React.Suspense fallback={cutonFallBack || <>...</>}>
          {<Child></Child>}
        </React.Suspense>
      )
    }
  }
}
复制代码

次に、全体的なリファクタリングされたコードはおおよそ次のようになります

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>)
    },
  ])
}
复制代码

em ~~~シンプルで気取らないですが、コードはずっと快適に見えます。私の友人は、私がたくさんの良いことを学んだことを嘆きました。これが基本的な操作、233333だと思います。

おすすめ

転載: juejin.im/post/7085674288933502984