阅读 772

React18 + Vite + Typescript开发一个TODO List

这是我参与更文挑战的第4天,活动详情查看: 更文挑战

第一章:环境搭建

由于前端圈已经被React 18和Vite刷爆了,秉着尝鲜的想法,决定使用React18 + Vite + Typescript开发一个TODO List。

React 18

React在昨天刚刚在官网发布了有关于React 18的计划更新(The Plan for React 18 – React Blog),同时发布了 Alpha 版本的 npm 包。在React 18发布时,它具有以下特点:

  • 将包含开箱即用的改进(如automatic batching)
  • 全新的 API(如startTransition
  • 内置支持了React.lazy的全新SSR架构
  • 可渐进的升级策略。相比于之前要么不升要么全升的一刀切方式,只有由新特性触发的更新会启用并发渲染.

Vite

vite —— 一个由vue作者尤雨溪开发的web开发工具,它具有以下特点:

💡 极速的服务启动: 使用原生ESM文件,无需打包!

⚡️ 轻量快速的热重载: 无论应用程序大小如何,都始终极快的模块热重载(HMR)

🛠️ 丰富的功能: 对TypeScript、JSX、CSS等支持开箱即用。

📦 优化的构建: 可选“多页应用”或“库”模式的预配置Rollup构建

🔩 通用的插件: 在开发和构建之间共享Rollup-superset插件接口。

🔑 完全类型化的API: 灵活的API和完整TypeScript类型。

解决了使用JavaScript开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用HMR,文件修改后的效果也需要几秒钟才能在浏览器中反映出来的问题。

新建项目

vite初始化

先用Vite初始化一个项目。文档传送门

# npm 6.x
npm init @vitejs/app todo-list --template react-ts

# npm 7+, 需要额外的双横线:
npm init @vitejs/app todo-list -- --template react-ts

# yarn
yarn create @vitejs/app todo-list --template react-ts
复制代码

安装依赖

# yarn
yarn
# npm
npm install
复制代码

更新react版本

由于package.json里面内置react版本是17.0.2,所以我们需要安装alpha版本

# yarn
yarn add react@alpha react-dom@alpha
# npm 
npm i react@alpha react-dom@alpha -S
复制代码

更新vite.config.js

使用ESBuild帮我们自动注入JSX的转换函数,但是需要注意的是,这里依旧采用的React.createElement的功能,而不是React 17 jsx。如果你想要React 17的新功能,你需要配置一个ESbuild插件来帮忙解决这个问题,详细可以可以看这个issue

export default defineConfig({
  plugins: [reactRefresh()],
  esbuild: {
    jsxInject: `import React from 'react'`
  }
})
复制代码

由于我们没有手动的导入React,所以我们需要让typescript知道。所以我们同时需要修改tsconfig.json:

{
    compilerOptions: {
        ...,
        "jsx": "react-jsx",
    }
}
复制代码

修改main.tsx

import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
const root = ReactDOM.createRoot(
  document.getElementById('root')
);
root.render(<App />);
复制代码

修改App.jsx

import { useState } from "react";
import logo from "./logo.svg";
import "./App.css";
function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>Hello Vite + React!</p>
        <p>
          <button type="button" onClick={() => setCount((count) => count + 1)}>
            count is: {count}
          </button>
        </p>
      </header>
    </div>
  );
}
export default App;
复制代码

这时候我们执行yarn dev

yarn dev
复制代码

忽然发现报了这样的错误:Property 'createRoot' does not exist on type 'typeof import("/code/my-app/node_modules/@types/react-dom/index")'. TS2339。这事因为现有的@types/react,@types/react-dom里面没有定义createRoot API,所以Typescript编译器不知道什么是createRoot,这时候需要升级@types/react,@types/react-dom

Typescript识别新API

升级@types/react,@types/react-dom,如果出现选择选择,选择最高版本即可。

yarn add @types/react @types/react-dom
复制代码

我们从看@types添加了api支持的PR,我们会找到一些提示。

/**
 * These are types for things that are present in the upcoming React 18 release.
 *
 * Once React 18 is released they can just be moved to the main index file.
 *
 * To load the types declared here in an actual project, there are three ways. The easiest one,
 * if your `tsconfig.json` already has a `"types"` array in the `"compilerOptions"` section,
 * is to add `"react/next"` to the `"types"` array.
 *
 * Alternatively, a specific import syntax can to be used from a typescript file.
 * This module does not exist in reality, which is why the {} is important:
 *
 * ```ts
 * import {} from 'react/next'
 * ```
 *
 * It is also possible to include it through a triple-slash reference:
 *
 * ```ts
 * /// <reference types="react/next" />
 * ```
 *
 * Either the import or the reference only needs to appear once, anywhere in the project.
 */
复制代码

所以我们需要编辑tsconfig.json,并要在compilerOptions下面添加一个选项:

{
    compilerOptions: {
        ...,
        "types": ["react/next", "react-dom/next", "src/types", "node_modules/@types"]
    }
}
复制代码

我们再次执行yarn dev

yarn dev
复制代码

这时候又会发现这样一个错误:Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Element | Document | DocumentFragment | Comment'. Type 'null' is not assignable to type 'Element | Document | DocumentFragment | Comment'. TS2345。原因是tsconfig中设置compilerOptions.strict = trueReactDOM.createRoot(rootElement)并不能保证返回的值非null,所以我们再次修改main.tsx文件。

再次修改main.tsx

import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
const rootElement = document.getElementById("root");
if (!rootElement) throw new Error("Failed to find the root element");
const root = ReactDOM.createRoot(rootElement);
root.render(<App />);
复制代码

我们再次执行yarn dev

yarn dev
复制代码

大功告成。🎆🎆。又见到我们熟悉的页面:

image.png 下一章,我们将使用React18全新API进行开发,记得点赞关注收藏!!!

文章分类
前端
文章标签