使用 React18 + Vite + TypeScript 完成公司项目经验总结

当前找工作环境恶劣,很多求职者表示招聘不仅要求会 vue,还要求会 react。

刚好这段时间我用 React18 + Vite + TS 为公司从 0 到 1 开发了一个项目,就顺便总结了一些前端开发知识和技巧,帮助我记忆这些知识的同时,希望能对你也有所启发。欢迎评论区交流。

我会把代码(当然不是真实项目的。。)上传到 GitHub 上,文末可以取链接。最后还请多多评论、点赞支持!废话不多说,下面开始进入正题:

创建项目

选择 React + TypeScript 模板。不要选用 React + TypeScript + SWC。因为 SWC 不支持 babel 插件,不能转换 es6 语法和特性。这个后面也会说到。

pnpm create vite复制代码
图片[1]-使用 React18 + Vite + TypeScript 完成公司项目经验总结-山海云端论坛

如何配置

根据官网的说明,只需要简单的执行下面的命令,然后根据你的项目进行选择配置。

pnpm create @eslint/config复制代码
图片[2]-使用 React18 + Vite + TypeScript 完成公司项目经验总结-山海云端论坛

让 eslint 检查缩进

如果我想让所有代码的索引为 2 个空格,否则就报错误,那么如何配置呢?

在 .eslintrc.cjs 文件中。

module.exports = {  rules: {    // 缩进必须为 2 个空格 https://eslint.org/docs/latest/rules/indent#rule-details    "indent": ['error', 2],    // 禁止所有 tab https://eslint.org/docs/latest/rules/no-tabs#rule-details    'no-tabs': 'error',  }}复制代码

禁用 tab 表示缩进使用 spaces,而不是 tab。可以在 vscode 右下角查看配置。

图片
image.png

使用 eslint-plugin-react-hooks 插件

这个插件是在上面那个清单里看到的。可以检查我们写的 react hook 是否规范。

add eslint-plugin-react-hooks --dev复制代码

然后扩展 eslint 配置

{  "extends": [    // ...    "plugin:react-hooks/recommended"  ]}复制代码

TypeScript 技巧

怎么定义全局类型

比如我想在全局都能使用以下几个类型

type pageview = 'pageview'type click = 'click'type blockview = 'blockview'type elementview = 'elementview'复制代码

就在 global.d.ts 文件里进行定义,然后就可以在全局里使用啦。但是要确保 global.d.ts 文件包含在 tsconfig.json 文件的 include 选项中。

declare global {  declare type pageview = 'pageview'  declare type click = 'click'  declare type blockview = 'blockview'  declare type elementview = 'elementview'}复制代码

如何获取数组类型的元素类型

type ListType = {a:number,b:string}[]const list = [{}] as ListType// 法一type ArrayItem<T> = T extends Array<infer R> ? R : nevertype Item = ArrayItem<ListType>// 法二TaskList['task'][number]type Item = ListType[number]复制代码

setState 传入回调函数场景

假设 age 为 42,这个方法将会调用 setAge(age + 1) 三次。

function handleClick() {  setAge(age + 1); // setAge(42 + 1)  setAge(age + 1); // setAge(42 + 1)  setAge(age + 1); // setAge(42 + 1)}复制代码

然而,触发 handleClick 方法后,age 还是 43,不是 45。因为 set 方法不会更新 age 状态变量在当前正在运行的代码。所以每次 setAge(age + 1) 都变成 setAge(43)。

为了解决这个问题,你可以传一个函数类型参数给 setAge,获取到下一会的状态。

function handleClick() {  setAge(a => a + 1); // setAge(42 => 43)  setAge(a => a + 1); // setAge(43 => 44)  setAge(a => a + 1); // setAge(44 => 45)}复制代码

a => a + 1 是你的更新函数。它接收一个待改变的 state,然后在函数体计算返回下一个 state。

React 把更新函数放入一个队列中。然后在下一次 render 时,更新函数将会以相同的顺序被调用。

  1. a => a + 1 将接收 42 作为待改变的状态,然后返回 43 作为下一次的状态。
  2. a => a + 1 将接收 43 作为待改变的状态,然后返回 44 作为下一次的状态。
  3. a => a + 1 将接收 44 作为待改变的状态,然后返回 45 作为下一次的状态。
  4. 没有其它队列需要更新, 最后 React 将会存储 45 作为最后的状态。

在开发模式下,React 可能会调用两次你的更新函数,目的是保他们是纯的没有副作用。

理解 useRef、useMemo、useCallback

useRef 可用来存储一个引用值(不会受 re-render 影响),也可用来获取 dom 节点。

useMemo 用来缓存一个值。当依赖项为空数组时,缓存值永远不会变。当有依赖性时,每次 re-render 如果依赖改变,那么将重新执行函数,将新的函数返回值作为缓存的数据。

useCallback 是 useMemo 的语法糖,相当于返回一个函数。

  const fn1 = useCallback(() => {    console.log(123);  }, [])  const fn2 = useMemo(() => () => {    console.log(123);  }, [])复制代码

react 不会缓存组件状态的解决方案

react 不像 vue 能使用 keep-alive。

当 react 跳到另外一个页面,再返回到上一个页面。上一个页面会重新渲染。

由于水平有限,所以决定将接口数据进行缓存。第一次没有缓存会请求。第二次执行方法时判断是否有缓存,有就直接返回缓存的数据。

我觉得要理解这个 hook,要明白模块只会被加载一次。还要明白每次 re-render 有些方法是会被重新执行,有些方法是会被重新定义。

useCache hook

interface Cb {  (...arg: unknown[]): unknown}const cacheMap = new Map();export default (key: string, callback: Cb) => {  return async (cache = true) => {    const result = cacheMap.get(key)    if(cache && result) {      return result    }    const res = await callback()    cacheMap.set(key, res)    return res  }}复制代码

使用

function App () {    const [count, setCount] = useState(0)  useEffect(() => {    fn()  })  async function fn () {    const res = await getStatus()     console.log('===>', res);  }  const getStatus = useCache('getStatus', () => {    const arr = [1,2,3,4]    const res = [] as number[]    arr.forEach(num => {      console.log(num);      res.push(num)    });    return res  })  function add () {    setCount(c => c + 1)  }  return (    <>      <h2>==</h2>      <br />      {count}      <br />      <button onClick={add}>add</button>      <h2>==</h2>    </>  )}复制代码

react-router-dom 简单使用

页面跳转管理 使用 react-router-dom

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容