# react18
**Repository Path**: adu7/react18
## Basic Information
- **Project Name**: react18
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-10-31
- **Last Updated**: 2025-11-09
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
-
| 格式 | 显示 |
| ----------- | ---- |
| `ctrl + B` | 加粗 |
| `ctrl + I ` | 斜体 |
| `ctrl + # ` | 标题 |
| `ctrl + T ` | 表格 |
-
| 代码 | 显示 |
| ------------------ | ---------- |
| `ctrl + Shift + B` | 行内代码 |
| `ctrl + Shift + K` | 多行代码 |
| `ctrl + K` | 下划线链接 |
# React18
> vscode插件
1. TRAE AI
2. comate
```
创建
pnpm create vite@latest
```
> 项目目录
```
eslint.config.js //代码规范
tsconfig.app.json //针对整个项目
tsconfig.json
tsconfig.node.json //只针对vite.config.ts
vite.config.ts
pubilc
打包会放在dist根目录
src
/assets 需要构建 加hash
```
> package.json
```
{
"name": "test_react18",
"private": true,
"version": "0.0.0",
"type": "module",
//对应nodemodules/bin
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
//开发环境 不会打包
"devDependencies": {
"@eslint/js": "^9.15.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"@types/node": "^24.6.0",
"eslint": "^9.15.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"globals": "^15.12.0",
"typescript": "~5.6.3",
"typescript-eslint": "^8.15.0",
"vite": "^6.0.1"
}
}
```
## babel
> js编译器 AST语法树(桥梁) -> Tranform -> Generate
```
es6 es7 -> es5
jsx -> javascript
核心库
@babel/core
@babel/generate
```
## jsx
## useState
```
const handle = () => {
setCount(count + 1);//count + 1为状态
setCount(count + 1);
setCount(count + 1); //异步跟新 react只在意最后的状态,不关心过程
};//1
const handle = () => {
setCount((prev)=>prev+1);//(prev)=>prev+1为过程
setCount((prev)=>prev+1);
setCount((prev)=>prev+1); //异步跟新 react只在意最后的状态,不关心过程
};//3
const handle = () => {
setCount(1);
setCount(2);
setCount(3); //异步跟新 react只在意最后的状态,不关心过程
};//3
```
## useEffet
> 依赖项更新时先执行cleanup 在执行setup 卸载时执行cleanup 返回undefined
```
00:01
useEffect概述
1.useEffect是React中处理副作用的钩子函数,类似于生命周期方法。
2.useEffect可以在组件渲染完成、更新和卸载时处理副作用。
00:38
纯函数与副作用函数
1.纯函数:相同的输入永远得到相同的输出,不依赖外部状态,也不修改外部状态。
2.副作用函数:依赖外部状态,或在执行过程中修改外部状态。
3.常见副作用函数:修改localStorage、发送Ajax请求、操作DOM元素等。
02:56
纯函数的实现
1.不直接修改原始数据,而是创建数据的副本进行修改。
2.深拷贝:使用库函数或手动实现,确保复制对象及其所有嵌套属性。
3.浏览器原生API:使用结构化克隆或库函数进行深拷贝。
```
## useReducer
```
const initState = {
count: -1,
};
//初始化函数 只执行一次
const initfn = (state: { count: number }) => {
console.log(state, '初始化函数 只执行一次');
return {
count: 10,
};
};
// 处理函数reducer 默认不走
const reducer = (state: { count: number }, action: { type: string }) => {
// return state;
console.log(state, action, '处理函数reducer');
switch (action.type) {
case 'add':
return {
count: state.count + 1,
};
case 'sub':
return {
count: state.count - 1,
};
default:
return state;
}
};
function App() {
//第二个参数为默认值
// 第三个参数是可选的,可不传
const [state, dispath] = useReducer(reducer, initState, initfn);
return (
<>
{state.count}
>
);
}
```
## useSyncExternalStore
```
useStorage.ts
import { useSyncExternalStore } from 'react';
export const useStorage = (type: string, initValue: any) => {
// 订阅者
const subscribe = (callback: () => void) => {
// 订阅浏览器api
window.addEventListener('storage', callback); //callback刷新视图
return () => {
//取消订阅
window.removeEventListener('storage', callback);
};
};
const getSnapshot = () => {
//返回值和上一次不同 视图就会更新 注意:数组等引用类型时需返回新的引用
return localStorage.getItem(type) || initValue;
};
const res = useSyncExternalStore(subscribe, getSnapshot);
const updateStorage = (value: any) => {
localStorage.setItem(type, JSON.stringify(value));
window.dispatchEvent(new StorageEvent('storage')); //通知订阅者
};
return [res, updateStorage];
};
useHistory.ts
import { useSyncExternalStore } from 'react';
// 实现跳转 监听history变化
export const useHistory = () => {
// 订阅者
const subscribe = (callback: () => void) => {
// 订阅浏览器api 监听路由的变化
// vue的三种路由结构 ssr hash history
// hash 监听hashchange 注意 只能监听浏览器的前进后退按钮
// history 监听popstate 注意 只能监听浏览器的前进后退按钮
// ssr 监听popstate
window.addEventListener('hashchange', callback); //callback刷新视图
window.addEventListener('popstate', callback);
return () => {
//取消订阅
window.removeEventListener('storage', callback);
window.removeEventListener('popstate', callback);
};
};
const getSnapshot = () => {
return window.location.href;
};
const url = useSyncExternalStore(subscribe, getSnapshot);
const push = (url: string) => {
window.history.pushState({}, '', url);
window.dispatchEvent(new PopStateEvent('popstate')); //手动触发popstate事件
};
const replace = (url: string) => {
window.history.replaceState({}, '', url);
window.dispatchEvent(new PopStateEvent('popstate')); //手动触发popstate事件
};
return [url, push, replace] as const;
};
```
## useTranstion
```
```

> 优化hooks
> 帮助你在不阻塞UI的情况下更新状态的React Hooks
> 用于管理UI中的过渡状态 特别是处理长时间运行的状态更新时,它允许你将某些更新标记为过渡状态,这样React可以优先处理更重要的更新,比如用户输入,同时延迟处理过渡更新
```
pnpm i mockjs
pnpm install antd --save
import type React from "react";
import { Input, List } from "antd";
import { useState, useTransition } from "react";
const Ces: React.FC = () => {
const [inputvalue, setInputValue] = useState("");
const [list, setList] = useState([]);
const [isPending, startTransition] = useTransition();
interface ListItem {
id: string;
name: string;
age: number;
sex: string;
address: string;
}
const handleChange = (e: React.ChangeEvent) => {
console.log(e.target.value);
setInputValue(e.target.value);
fetch(`/api/mock/list?key=${e.target.value}`)
.then((res) => res.json())
.then((res) => {
// console.log(res);
setList(res.list);
// startTransition(() => {
// setList(res.list);
// });
});
};
return (
<>
{item.address}}
>
{/* {isPending ? (
Loading...
) : (
{item.address}}
>
)} */}
>
);
};
export default Ces;
```
## vite插件
```
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import type { Plugin } from 'vite';
import mockjs from 'mockjs';
import url from 'node:url';
const viteMockServer = (): Plugin => {
return {
name: 'vite-plugin-mock',
configureServer: (server) => {
server.middlewares.use('/api/mock/list', (req, res) => {
res.setHeader('Content-Type', 'application/json');
const parseurl = url.parse(req.originalUrl!, true).query;
const data = mockjs.mock({
'list|2000': [
{
'id|+1': '@guid',
name: parseurl.key,
age: '@integer(18, 30)',
'sex|1': ['男', '女'],
address: '@county(true)',
},
],
});
res.end(JSON.stringify(data));
});
},
};
};
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), viteMockServer()],
server: {
port: 3008,
},
});
```
## useDeferredValue


```
import type React from "react";
import { Input, List } from "antd";
import { useDeferredValue, useState } from "react";
import mockjs from "mockjs";
const Ces: React.FC = () => {
const [inputvalue, setInputValue] = useState("");
const [list, setList] = useState(() => {
return mockjs.mock({
"list|100": [
{
id: "@guid",
name: "@cname",
age: "@integer(18, 30)",
sex: "@boolean",
address: "@county(true)",
},
],
}).list;
});
interface ListItem {
id: string;
name: string;
age: number;
sex: string;
address: string;
}
const inputvalueDeferred = useDeferredValue(inputvalue);
const handleChange = (e: React.ChangeEvent) => {
console.log(e.target.value);
setInputValue(e.target.value);
};
const findName = () => {
return list.filter((item) => item.name.includes(inputvalueDeferred));
};
const isSame = () => {
return inputvalueDeferred === inputvalue;
};
return (
<>
(
{item.name}
{item.address}
)}
>
>
);
};
export default Ces;
```
## useRef


```
import React, { useRef } from "react";
const Ces: React.FC = () => {
const domRef = useRef(null);
//null 表示一个空对象
//undefined obj obj.a的a 没有定义 就为undefined
const handleClick = () => {
console.dir(domRef.current);
domRef.current!.style.color = "red";
};
return (
<>
AAA
BBB
CCC
>
);
};
export default Ces;
import React, { useRef, useState } from "react";
const Ces: React.FC = () => {
const domRef = useRef(null);
const [count, setCount] = useState(0);
// let num = 0;
let num = useRef(0);
console.log("App -- render");
// useState 每次渲染都会重新创建Ces这个组件 num也会初始化为0
const handleClick = () => {
setCount((old) => {
num.current = old + 1;
return old + 1;
});
console.log(num, count);
};
return (
<>
数据存储
{count}:{num.current}
>
);
};
export default Ces;
```
## useImperativeHandle


```
import React, { useImperativeHandle, useRef, useState } from "react";
const Son = React.forwardRef((props, ref) => {
const [count, setCount] = useState(0);
useImperativeHandle(
ref,
() => ({
getCount() {
console.log("getCount");
},
count,
setCount,
}),
[]
);
return (
子组件:{count}
);
});
const Ces: React.FC = () => {
const childRef = useRef(null);
const handleClick = () => {
console.log(childRef.current.count);
};
const handleAdd = () => {
childRef.current.setCount(childRef.current.count + 1);
};
return (
<>
我是父组件
>
);
};
export default Ces;
主要用于弹窗父子组件 子组件将form校验等函数暴露出去
import React, { useImperativeHandle, useRef, useState } from "react";
const Son = React.forwardRef((props, ref) => {
const [form, setForm] = useState({
name: "",
password: "",
});
const vaidator = () => {
console.log(form);
if (form.name.length === 0) {
return "name不能为空";
}
if (form.password.length === 0) {
return "password不能为空";
}
};
const resetForm = () => {
setForm({
name: "",
password: "",
});
};
useImperativeHandle(
ref,
() => ({
vaidator,
resetForm,
})
);
return (
);
});
const Ces: React.FC = () => {
const childRef = useRef(null);
const handlevaidator = () => {
console.log(childRef.current.vaidator());
};
const handlereset = () => {
childRef.current.resetForm();
};
return (
<>
我是父组件
>
);
};
export default Ces;
```
## useContext


```
import React, { useImperativeHandle, useRef, useState } from "react";
interface ThemeContextType {
theme: string;
}
const ThemeContext = React.createContext({
theme: "light",
});
const Sonson = () => {
const { theme } = React.useContext(ThemeContext);
console.log(theme, "sonson");
const lightStyle = {
color: "white",
backgroundColor: "black",
};
const darkStyle = {
color: "black",
backgroundColor: "white",
};
return sonson
;
};
const Son = () => {
const { theme } = React.useContext(ThemeContext);
console.log(theme, "son");
const lightStyle = {
color: "white",
backgroundColor: "black",
};
const darkStyle = {
color: "black",
backgroundColor: "white",
};
return (
);
};
const Ces: React.FC = () => {
const [theme, setTheme] = useState("light");
const handleClick = () => {
setTheme(theme === "light" ? "dark" : "light");
};
return (
<>
>
);
};
export default Ces;
```
## React原理







## 调度器


## TS

> 区别:接口和type区别

> keyof
>
> 

## reactRouter
> pnpm i react-router-dom


```
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import ReactDemo from "./React.tsx";
import EmptyPage from "./404.tsx";
import "./components/Message/index.tsx";
import {
BrowserRouter,
Routes,
Route,
Navigate,
HashRouter,
} from "react-router-dom";
createRoot(document.getElementById("root")!).render(
{/* */}
} />
} />
} />
);
function App() {
//第二个参数为默认值
// 第三个参数是可选的,可不传
const [state, dispath] = useReducer(reducer, initState, initfn);
const [count, setCount] = useStorage('ss', 22);
const [url, push, replace] = useHistory();
return (
<>
NavLink to home
Link to home
{state.count}
{/* {count}
{url}
*/}
{/* */}
>
);
}
```