Build webpack + React Hooks + TypeScript + Antd

React react-hot-loader React-router loadable typescript

The new App. JSX

Move the App function from SRC /index.js to SRC/app.js

src/App.js

import React from 'react'; Function App() {return (<div>==start?? , ==</div>)} export default App;Copy the code

src/index.js

import App from './App';
Copy the code

An error occurs during run

Need to change to
App.jsx
To run
import App from './App.jsx';
Copy the code
If you don’t want to write the suffix every time, you can introduce it in webpack.common.js
// ...
module: { ... },

+ resolve: {
+   extensions: ['.jsx', '.js'],
+ },

plugins: [ ... ]
Copy the code
They go looking for it
js jsx
File with suffix
The current changes
index
Save the file, the browser will refresh the update, to achieve no refresh update can be installed
react-hot-loader

Install the react – hot – loader

yarn add react-hot-loader -D
Copy the code

babel.config.js

const plugins = [
+    ['react-hot-loader/babel'],
];
Copy the code

Webpack.dev.js configures hot: true

DevServer: {contentBase: '. / dist, host: '0.0.0.0' public: ` ${process. The env. DEV_HOST | | localhost} : 8080 ` + hot: true, },Copy the code

New in SRC/App. Js

import { hot } from 'react-hot-loader/root';

export default hot(App);
Copy the code
again
run
It prints in the browser

The update succeeded without refreshing

Start installing and configuring typescript

yarn add typescript -D
Copy the code
To install @ Babel/preset – typescript to compile ts [see address] (https://babeljs.io/docs/en/babel-preset-typescript)
yarn add @babel/preset-typescript -D
Copy the code
Tsconfig. json file is added to the root directory to tell TS how to compile the file

tsconfig.json

{  
  "compilerOptions": {    
    "jsx": "react",    
    "outDir": "./dist/",    
    "isolatedModules": true,    
    "strict": true,    
    "noUnusedLocals": true,    
    "noUnusedParameters": true,    
    "noFallthroughCasesInSwitch": true,    
    "moduleResolution": "node",    
    "esModuleInterop": true,    
    "allowSyntheticDefaultImports": true,    
    "allowJs": true,    
    "baseUrl": "./",    
    "target": "es5",    
    "module": "ESNext",    
    "noImplicitAny": true  
 },  
 "include": ["src/**/*", "types/*"]
}
Copy the code

Change the entry file suffix to TSX

Build/webpack.com mom. Js modified

entry: './src/index.tsx',

module: {
    rules: [
     {
        test: /\.(jsx?|tsx?)$/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
   ],
},

resolve: {
    extensions: ['.tsx', '.ts', '.js'],
},
Copy the code
Will find index. The TSX and App. TSX file error, [see] (https://www.jianshu.com/p/35742227738e/) TypeScript third-party packages are introduced, the module error cannot be found

There are two ways to do it
  1. Follow the error message and try to install the TypeScript version of the library (its TS declaration file) by prefacing the library’s name with @types/

  2. Create the XXX.d. t declaration file

Here ** first ** choose method 2

Create the types folder in the root directory and create the index.d.ts file

types/index.d.ts

declare module 'react';
declare module 'react-dom';
Copy the code

The error has been resolved

But using Hooks requires making sure the component returns

Therefore, remove the configuration of method 1 and install it directly

Install @ types/react @ types/react – dom

yarn add @types/react @types/react-dom -D
Copy the code

Then all errors are resolved and typescript is configured

Install the react – the router – the dom

yarn add react-router-dom
Copy the code

Create the pages and Routes folders under SRC. Create the home and About folders under Pages. Add the home and about files to the index. TSX files respectively

src/pages/home/index.tsx

import React from 'react'; 

const Home: React.FC = () => {
    return (
        <div>Home</div>
    )
}

export default Home;
Copy the code

src/pages/about/index.tsx

import React from 'react'; 

const About: React.FC = () => {    
    return (
        <div>About</div>
    )
}

export default About;
Copy the code

Configure the alias in webpack.common.js

build/webpack.common.js

resolve: { extensions: ['.tsx', '.ts', '.js'], + alias: { + '@pages': resolve('.. /src/pages'), + }, },Copy the code

Ts and index. TSX are created in the routes folder. Home and About are introduced in config.ts, but an error occurs

src/routes/config.ts

Ts module @pages/home cannot be found. You need to configure the same path in tsconfig and compilerOptions in tsconfig.ts

tsconfig.ts

{  
  "compilerOptions": {    
    ...
+   "paths": {
+      "@pages/*": ["./src/pages/*"],
+   }
 },  
 "include": ["src/**/*", "types/*"]
}
Copy the code

If you need to configure the tsconfig file to introduce other aliases later, the error is resolved

And I’ll say routes

src/routes/config.ts

import Home from '@pages/home'; / /... Compont export interface IRouteItem {name: string; path: string; exact: boolean; component: React.FC; title? : string; meta? : any; needAuth? : boolean; }; Export const routes: IRouteItem[] = [{name: 'Index', path: '/', exact: true, Component: Home, title: 'Home ', meta: {},}, {...},];Copy the code

src/routes/index.tsx

import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import { routes, IRouteItem } from './config'; export default function Routes() { return ( <BrowserRouter> <Switch> {routes.map(route => { const { name, path, exact, component: Component, ... rest } = route; return ( <Route key={name} path={path} exact={exact} render={routeProps => { return ( <Component {... routeProps} /> ); }} ></Route> ); })} </Switch> </BrowserRouter> ); }Copy the code

Add /home to the page url to find page 404

The react-router path setting was invalid with error message Cannot GET/XXX

Add it to devServer

build/webpack.dev.js

DevServer: {contentBase: '. / dist, host: '0.0.0.0' public: ` ${process. The env. DEV_HOST | | localhost} : 8080 `, hot: true, + historyApiFallback: true, },Copy the code

But in VScode, Component reports an error

This is because the components in Home and About inherit React.FC

const About: React.FC = () => {
Copy the code

RouteProps is the router returned by the React Router

RouteComponentProps or RouteProps can be imported from the React-Router

src/routes/config.ts

+ import { RouteComponentProps, RouteProps } from "react-router";
Copy the code

So IRouteItem rewrites component: react. FC to react.componentType

;

Or component: React.Com ponentType < RouteComponentProps >;

See TypeScript + React best practices – Section 1: Component typing

SRC/routes/config. Ts IRouteItem modification

export interface IRouteItem { name: string; path: string; exact: boolean; - component: React.FC; + component: React.ComponentType<RouteProps>; title? : string; meta? : any; needAuth? : boolean; };Copy the code
The ts error is resolved

However, importing all components directly would result in too much packaging, so react-loadable should be introduced for on-demand loading

Install the react – loadable

yarn add react-loadable -D
Copy the code

src/routes/config.ts

+ import Loadable from 'react-loadable';
Copy the code
But TS errors are reported

Install the Loadable TS declaration file

yarn add @types/react-loadable -D
Copy the code

SRC /routes/config.ts introduces loadable

import Loadable, { LoadingComponentProps } from 'react-loadable';
Copy the code

Write another loading transition function
function LoadPage() { return ( <div>loading... </div> ); }Copy the code
Query loadable nonde_modules source code to introduce generics, modify the imported content

New in SRC/routes/config. Ts

type ComponentType = React.ComponentType<RouteComponentProps> | React.ComponentType<any>; interface ILoadable<Props> { loader(): Promise<React.ComponentType<Props> | { default: React.ComponentType<Props> }>; loading? : React.ComponentType<LoadingComponentProps>; } function loadable<Props>(props: ILoadable<Props>) { return Loadable({ loading: LoadingPage, delay: 300, ... props, }); }Copy the code
Finally, modify the Home and About introduced

src/routes/config.ts

- import Home from '@pages/home'; - import About from '@pages/about'; const Home: ComponentType = loadable({ loader: () => import('.. /pages/home'), }); const About: ComponentType = loadable({ loader: () => import('.. /pages/about'), });Copy the code

src/pages/home/index.tsx

+ import { Link } from "react-router-dom"; const Home: React.FC = () => { return ( <> <div>Home</div> + <Link to="/about">to about</Link> </> ) } export default Home;Copy the code

The browser finds that Home and About have been packaged separately

Click on the
to about

On the success of lazy loading (*^▽^*)

Search is usually passed in as query in a page

Change the url argument to object

src/routes/index.tsx

const query = Object.fromEntries(new URLSearchParams(location.search.substr(1)));
Copy the code
but
ts
An error

Because target is specified as a lower version in tsconfig.ts for compatibility reasons"target": "es5"If a higher ES version is used, ts displays an error message. You can change toESNextFor details, seeTs compilation optionsAfter the modification, ts does not display an error, but query still displays an error

That’s because RouteComponentProps doesn’t have query on its ComponentProp. Check the RouteComponentProps source code at 👇

So in config.ts you can override an interface that inherits RouteComponentProps

src/routes/config.ts

interface IComponentProps extends RouteComponentProps { query? : { [key: string]: any; }; } type ComponentType = React.ComponentType<IComponentProps> | React.ComponentType<any>;Copy the code

The error has disappeared

The page can also get the query directly from props, rather than parsing the URL argument each time. The props of Home or About can print it out

React-hot-loader react-router loadable typescript configures CSS less CSS-modules

later

Install webpack + React Hooks + TypeScript + Antd

Install webpack + React Hooks + TypeScript + Antd

Build webpack + React Hooks + TypeScript + Antd