# react **Repository Path**: Suger-ay/react ## Basic Information - **Project Name**: react - **Description**: 学习笔记 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-12-10 - **Last Updated**: 2025-12-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README React 学习笔记(React + Vite) React 官网:https://zh-hans.react.dev/ Vite 官网:https://cn.vitejs.dev/ ReactRouter 官网:https://reactrouter.com/start/modes ##### 1. 创建项目 ```bash npm create vite@latest ``` ##### 2. 目录结构 ```jsx // 这里定义的是全局常/变量,不会触发热更新 function App() { // 热更新js代码区 return(
{/* 组件区 */}

Hello React

; ) } ``` ##### 3. 组件 一个组件就是首字母大写的函数,内部存放了组件的逻辑和视图 UI,渲染组件只需要把组件当成标签即可,组件可以嵌套和复用。 ##### 4. Hook - 4.1 useState 状态变量 react 中的状态始终被认为是只读的,不能直接修改,否则不会触发视图更新,需要通过 setState 方法重新赋值。 useState 返回一个数组,第一个值为状态变量,第二个值为修改状态变量的方法。 ```jsx // 表单受控绑定 const [value, setValue] = useState('') setValue(e.target.value)} /> ``` - 4.2 useRef 获取/操作 DOM 元素 useRef 返回一个对象,对象中有一个 current 属性,可以用来获取 DOM 元素,也可以用来存储数据,不会触发视图更新。 ```jsx // 获取DOM元素 const inputRef = useRef(null) // 以下需考虑生命周期 console.log('拿到的DOM对象:'+inputRef.current) // 聚焦 inputRef.current?.focus() ``` - 4.3 useEffect 副作用 useEffect 是一个副作用钩子,可以在组件渲染完毕后执行一些额外的操作,比如发送请求、订阅事件、修改 DOM 等。 useEffect 接受两个参数,第一个参数是一个函数,第二个参数是一个数组,数组中的元素是依赖项,当依赖项发生变化时,会重新执行 useEffect 中的函数,当是一个空数组的时候,副作用函数只会在数组渲染完成后执行一次。 ```jsx // 依赖项为空数组,只执行一次 useEffect(() => { console.log("组件渲染完毕"); }, []); ``` 关于依赖项特别说明: | 依赖项 | 副作用函数执行时机 | | :------------: | :-------------------------------: | | 没有依赖项 | 组件初始渲染+组件更新时执行 | | 空数组依赖 | 只在初始渲染时执行一次 | | 添加特定依赖项 | 组件初始渲染+特性依赖项变化时执行 | ```jsx import {useEffect, useState } from "react" function App{ const[count,setCount]=useState(0) // 1.没有依赖项 初始 + 组件更新 // useEffect(() => { // console.log("副作用函数执行了") // }) // 2.传入空数组依赖 初始执行一次 // useEffect(()=> { // console.log("副作用函数执行了") // },[]) // 3.传入特定依赖项初始 + 依赖项变化时执行 useEffect(()=>{ console.log("副作用函数执行了") },[count]) return (
this is app
) } export default App ``` 清除副作用 useEffect 返回一个函数,可以在组件卸载时执行一些清理操作,比如取消订阅、清除定时器等。 ```jsx useEffect(() => { // 执行副作用函数 return () => { // 清除副作用函数 最常见的执行时机是组件卸载时自动执行 }; }); ``` 自定义 Hook 名称以 use 开头,抽取可复用的逻辑,方便在组件中使用。 ```jsx import { useState } from "react"; function useToggle() { // 可复用的代码逻辑 const [value, setValue] = useState(true); const toggle = () => { setValue(!value); }; // return需要在组件中使用的状态和回调函数 []或{} return [value, toggle]; } function App() { // 使用自定义 Hook const [value, toggle] = useToggle(); return (
{value &&
this is a div
}
); } ``` 封装自定义 Hook 通用思路: - 1. 定义一个函数,函数名称以 use 开头 - 2. 函数内部封装可复用的逻辑 - 3. 返回需要复用的状态和回调函数 - 4. 在组件中解构自定义 Hook 返回的状态和回调函数,并使用 **Hooks 使用规则说明:** - 1. 只能在组件或其他自定义 Hook 函数中使用 - 2. 只能在组件顶层使用,不能嵌套在 if、for、try、其他函数中使用 ##### 5. 组件通信 - 5.1 父传子 父组件通过 props 传递数据给子组件,子组件通过 props 接收数据。 props 可以传递任意类型的数据,包括字符串、布尔值、函数、对象、数组、JSX 等。 ```jsx // 父组件 function Parent() { const [value, setValue] = useState("父组件传递的数据"); return (
); } // 子组件 function Child(props: { value: string }) { return
{props.value}
; } ``` props 是只读的,不能直接修改,父组件的数据只能由父组件修改。 **props children** ```jsx // 父组件 标签嵌套 我是span标签 ; // 子组件 通过props.children渲染在页面中 function Son(props: { children: React.ReactNode }) { return (

我是子组件


{props.children}
); } ``` - 5.2 子传父 子组件通过 props 传递数据给父组件,父组件通过 props 接收数据,并传递给子组件。 ```jsx // 父组件 function Parent() { const [value, setValue] = useState(""); const handleChildChange = (value: string) => { setValue(value); }; return (

{value}

); } // 子组件 function Child(props: { onChange: (value: string) => void }) { const [value, setValue] = useState(""); const handleChange = (e: React.ChangeEvent) => { setValue(e.target.value); props.onChange(e.target.value); }; return (
); } ``` - 5.3 兄弟组件 使用状态提升实现兄弟组件通信,即通过共同的父组件传递 ```jsx // 父组件 function Parent() { const [value, setValue] = useState(""); const handleChildChange = (value: string) => { setValue(value); }; return (
); } // 子组件1 function Child1(props: { onChange: (value: string) => void }) { const [value, setValue] = useState(""); const handleChange = (e: React.ChangeEvent) => { setValue(e.target.value); props.onChange(e.target.value); }; return (
); } // 子组件2 function Child2(props: { value: string }) { return (

{props.value}

); } ``` - 5.4 跨层组件通信——Context 机制 ```jsx // 1. 创建Context const MyContext = createContext(); // 2. 顶层组件通过Provider组件提供数据 function Parent() { const [value, setValue] = useState(""); const handleChildChange = (value: string) => { setValue(value); }; return ( ); } // 3. 子组件通过useContext钩子获取数据 function Child2() { const value = useContext(MyContext); return (

{value}

); } ``` - 5.5 跨层组件通信——Redux 机制 (集中状态管理工具) ```jsx // 1. 安装 // Redux Toolkit:是一套工具集,用于简化 Redux 的书写方式 // react-redux:链接React和Redux的中间件 npm i @reduxjs/toolkit react-redux // 2. 创建slice store/modules/counterStore.js import { createSlice } from "@reduxjs/toolkit"; import axios from "axios"; const counterSlice = createSlice({ name: "counter", // 命名空间 // 初始化状态 initialState: { count: 0 }, // 定义修改状态的方法 同步方法 支持直接修改 reducers: { increment(state) { state.count ++; }, decrement(state) { state.count --; }, // 支持传递参数 传递的参数会作为action.payload payload:固定的属性名 addToNum(state,action){ state.count+= action.payload }, }, }); const channelSlice = createSlice({ name: "channel", initialState: { channelList: [] }, reducers: { // 获取异步数据 setChannel(state,action){ state.channelList = action.payload } } }) // 解构actioncCreater函数 const { increment, decrement,addToNum } = counterSlice.actions; const { setChannel } = channelSlice.actions; // 发起异步请求 const getChannelList = () => { return async (dispatch)=>{ const res = await axios.get("http://localhost:3000/channel"); dispatch(setChannel(res.data)) } } const countReducer = counterSlice.reducer; const channelReducer = channelSlice.reducer; // 导出方法 export { increment, decrement, addToNum, getChannelList }; export default countReducer; export default channelReducer; // 3. 创建store store/index.js import { configureStore } from "@reduxjs/toolkit"; import counterReducer from "./counterSlice"; import channelReducer from "./channelSlice"; const store = configureStore({ reducer: { counter: counterReducer, channel: channelReducer, }, }); export default store; // 4. 在顶层组件中提供store App.js import { Provider } from "react-redux"; import store from "./store"; createRoot(document.getElementById("root")).render( ); // 5. 在子组件中获取store中的数据 useSelector:映射store中的数据 useDispatch:分发action import { useSelector, useDispatch } from "react-redux"; import { increment, decrement, addToNum, getChannelList } from "./counterSlice"; function Counter() { // 获取store中的数据 const count = useSelector((state) => state.counter); const list= useSelector((state) => state.channel); const dispatch = useDispatch(); // 触发请求 useEffect(()=>{ dispatch(getChannelList()) },[dispatch]) return (

{count}

{/* 传参 */} {/* 数据列表 */}
    {list.map((item) => (
  • {item.name}
  • ))}
); } ``` ##### 6. 路由——ReactRouter ```js // 1. 安装 v7 https://reactrouter.com.cn/ npm install react-router // 2.创建路由并绑定组件 router/index.js import { createBrowserRouter } from "react-router"; import Index from "../page/Index"; const router = createBrowserRouter([ // 普通路由 { path: "/", Component: Index, }, // 嵌套路由 { path: "/user", Component: User, children: [ { // path: "login", index: true,// 默认路由 Component: Login, }, { path: "register", Component: Register, }, ] } ]); export default router; // 3. 使用路由 main.js import { RouterProvider } from "react-router/dom"; import router from "./router/index.js"; createRoot(document.getElementById("root")).render( {/* */} {/* 绑定路由 */} ); // 嵌套 // 3.1 父组件 import { Outlet } from "react-router"; import { Link } from "react-router"; function User() { return (

用户

登录 注册 {/* 二级路由出口 */}
); } // 4. 路由导航 // 4.1 Link import { Link } from "react-router"; 首页 关于 // 4.2 NavLink 需要渲染活跃和待处理状态的导航链接 // https://reactrouter.com/start/framework/navigating#navlink import { NavLink } from "react-router"; // className [ isPending ? "pending" : "", isActive ? "active" : "", isTransitioning ? "transitioning" : "", ].join(" ") } > Messages // 4.3 Form
// 4.4 重定向redirect import { redirect } from "react-router"; export async function loader({ request }) { let user = await getUser(request); if (!user) { return redirect("/login"); } return { userName: user.name }; } // 4.5 编程式 useNavigate import { useNavigate } from "react-router"; export function useLogoutAfterInactivity() { let navigate = useNavigate(); useFakeInactivityHook(() => { navigate("/logout"); // 使用navigate函数并设置replace为true来替换当前历史记录 navigate("/logout", { replace: true }); }); } //4.6 路由导航传参 // 4.6.1 searchParams传参 navigate("/user?id=123"); // 取 const [params]=useSearchParams(); let id=params.get("id"); // 4.6.2 params传参 navigate("/user/123"); // 取 const [params]=useParams(); let id=params.id; ```