前言

常用链接

React官网React中文网CreateReact中文网Vite官网学习资料

创建项目的几种方式

使用NPM自带的NPX工具

不懂xpn是什么点我去查看

如果你之前通过 npm install -g create-react-app 全局安装了 create-react-app,我们建议你使用 npm uninstall -g create-react-appyarn global remove create-react-app 卸载软件包,以确保 npx 始终使用最新版本。

npx create-react-app react-ts-demo --template typescript
cd my-app
npm start

运行方式请根据指引操作或查看上面列举的链接文档查看

使用Vite包管理工具

在Vite官方的介绍中可以使用Vite命令来构建不同的模板:

我们可以使用如下命令来创建React项目的初始化工程

npm create vite@latest my-react-ts --template react-ts

运行方式请根据指引操作或查看上面列举的链接文档查看

可能会出现的问题

vite创建项目的方式启动的时候报错如下:

版本不兼容,换高版本Node解决,建议>=16+

规范代码插件配置(可忽略)

需安装EsLint以及Prettier插件

在项目根目录执行如下命令

npm install prettier eslint-config-prettier eslint-plugin-prettier --save-dev

在项目根目录中找到.eslintrc.cjs 文件,在extends 中添加如下代码:

'plugin:prettier/recommended'

全部代码如下:

module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react-hooks/recommended',
    'plugin:prettier/recommended'
  ],
  ignorePatterns: ['dist', '.eslintrc.cjs'],
  parser: '@typescript-eslint/parser',
  plugins: ['react-refresh'],
  rules: {
    'react-refresh/only-export-components': [
      'warn',
      { allowConstantExport: true },
    ],
  },
}

此时如果顺利的话,src下的App.tsx文件内会报错,要求引入文件需使用双引号,如果没有提示请重启VsCode在尝试

package.json 文件中添加一行命令:

"format": "prettier --write 'src/**/*.+(js|ts|jsx|tsx)'"

从控制台中执行npm format 会自动将不符合规则的代码自动进行修改,顺利的话你将会看到如下结果:

再回去查看App.tsx文件中的引入报错部分可以发现已经修改成双引号了:

保存自动进行格式处理

在项目根目录中新建.vscode 目录,在目录中新建settings.json 文件,添加如下代码:

{
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
}

可能会出现错误

'ts' 不是内部或外部命令,也不是可运行的程序

解决办法:

使用双引号包裹路径:在Windows中,使用双引号来包裹路径通常更加可靠。修改你的npm脚本,将format命令的路径参数用双引号包裹,如下所示:

 "format": "prettier --write \"src/**/*.+(js|ts|jsx|tsx)\""

JSX

React事件

React组件

useState

异步更新

import React, { FC, useState } from "react";

const StateDemo: FC = () => {
  // let count = 0;

  const [count, setCount] = useState(0);
  function add() {
    // count++;
    // set操作是异步的
    setCount(count + 1);
    // setCount((count) => count + 1);
    console.log(count);
  }

  return (
    <div>
      <button onClick={add}>add {count} </button>
    </div>
  );
};

export default StateDemo;

useState是异步更新,更新完会重新渲染页面

如果不需要用到组件中的值就无需使用useState,就算页面没有使用也会重新渲染

会合并的可能

如果是多条修改会合并成一条,如果是setState里面写的是函数则不会合并,函数只能一条一条更新

// 会合并成一条
 setCount(count + 1);
 setCount(count + 1);
 setCount(count + 1);
// 不会合并
 setCount(count =>{count + 1});
 setCount(count =>{count + 1});
 setCount(count =>{count + 1});

不可变数据

不可变数据: 不是去修改state值,而是要传入一个新的值

import React, { FC, useState } from "react";

const StateDemo02: FC = () => {
  const [userInfo, setUserInfo] = useState({ name: "SerMs", age: 20 });

  function changeAge() {
    // 不可变数据: 不是去修改state值,而是要传入一个新的值
    setUserInfo({
      //   name: "SerMs",
      ...userInfo,
      age: 32,
    });
  }

  const [list, setList] = useState(["x", "y"]);
  function addItem() {
    // concat 返回的是新数组
    // setList(list.concat("z"));
    setList([...list, "SerMs"]);
  }
  return (
    <div>
      <h2>state 不可变数据</h2>
      <div>{JSON.stringify(list)}</div>
      <button onClick={addItem}>change age</button>
      {/* <div>{JSON.stringify(userInfo)}</div>
      <button onClick={changeAge}>change age</button> */}
    </div>
  );
};

export default StateDemo02;

useEffect

  • React18开始,useEffect在开发环境下会执行两次

  • 模拟组件创建、销毁、在创建的完整流程,及早暴露问题

useRef

Dom操作

参考代码:

import React, { FC, useRef } from "react";

const UseRedDemo: FC = () => {
  const inputRef = useRef<HTMLInputElement>(null);

  function selectInput() {
    const inputElem = inputRef.current;
    if (inputElem) inputElem.select();
  }
  return (
    <div>
      <input ref={inputRef} type="text" defaultValue="hallo word" />
      <button onClick={selectInput}>选择</button>
    </div>
  );
};

export default UseRedDemo;

JS变量

可以传入普通JS变量,但不会触发组建的rerender

import React, { FC, useRef } from "react";

const UseRedDemo: FC = () => {
  const nameRef = useRef("SerMs"); // 不是DOM节点了, 普通的JS变量

  function changeName() {
    // 修改Ref值,不会触发rerender 使用state可以修改同时也会触发组件的rerender
    nameRef.current = "SerMsCoding";
    console.log(nameRef.current);
  }
  return (
    <>
      <p> name: {nameRef.current}</p>
      <div>
        <button onClick={changeName}>change Name</button>
      </div>
    </>
  );
};

export default UseRedDemo;

useMemo

作用:

  • 函数组件,每次state更新都会重新执行函数

  • useMemo可以缓存数据,不用每次执行函数都重新生成

  • 可以用于计算较大的场景,缓存提高性能(空间换时间)