当前位置: 首页 > news >正文

React 高级教程

使用 React 高级组件(HOC)实现的完整项目示例,包含权限控制、数据加载状态处理、性能优化等常见高级功能。创建一个简单的博客系统:

// 项目结构:
src/
|-- components/
|   |-- ArticleList.jsx
|   |-- Article.jsx
|   |-- Header.jsx
|   |-- LoginForm.jsx
|   |-- UserProfile.jsx
|   |-- WithLoading.jsx
|   |-- AuthContext.jsx
|   |-- WithAuth.jsx
|-- hocs/
|   |-- withAuth.js
|-- hooks/
|   |-- useFetch.js
|   |-- useDebouncedFetch.js
|-- contexts/
|   |-- UserContext.js
|-- pages/
|   |-- HomePage.jsx
|   |-- AdminPage.jsx
|   |-- LoginPage.jsx
|   |-- UserProfilePage.jsx
|   |-- ArticleDetailPage.jsx
|-- App.jsx
|-- index.js// 首先安装必要依赖:react-router-dom

关键技术点:

1. 创建认证上下文 (AuthContext.jsx)

import { createContext, useContext, useState } from 'react';const AuthContext = createContext();export function AuthProvider({ children }) {const [user, setUser] = useState(null);const login = (userData) => {setUser({ ...userData, role: 'admin' }); // 模拟登录};const logout = () => {setUser(null);};return (<AuthContext.Provider value={{ user, login, logout }}>{children}</AuthContext.Provider>);
}export const useAuth = () => useContext(AuthContext);

2. 创建高阶组件 (WithAuth.jsx)

import { useNavigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';export const withAuth = (WrappedComponent, requiredRole = 'user') => {return (props) => {const { user } = useAuth();const navigate = useNavigate();if (!user) {navigate('/login');return null;}if (requiredRole === 'admin' && user.role !== 'admin') {return <div>无权限访问此页面</div>;}return <WrappedComponent {...props} user={user} />;};
};

3. 加载状态高阶组件 (WithLoading.jsx)

import { useState, useEffect } from 'react';export const withLoading = (WrappedComponent, fetchData) => {return (props) => {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);useEffect(() => {const loadData = async () => {try {const result = await fetchData();setData(result);} catch (err) {setError(err.message);} finally {setLoading(false);}};loadData();}, []);if (loading) return <div>Loading...</div>;if (error) return <div>Error: {error}</div>;return <WrappedComponent {...props} data={data} />;};
};

4. 自定义 Hook (useFetch.js)

import { useState, useEffect } from 'react';export const useFetch = (url) => {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);useEffect(() => {const fetchData = async () => {try {const response = await fetch(url);const result = await response.json();setData(result);} catch (err) {setError(err.message);} finally {setLoading(false);}};fetchData();}, [url]);return { data, loading, error };
};

5. 优化列表组件 (OptimizedList.jsx)

import React from 'react';const OptimizedList = React.memo(({ items, renderItem }) => {console.log('List re-rendered');return (<div style={{ maxHeight: '500px', overflow: 'auto' }}>{items.map((item, index) => (<div key={item.id || index}>{renderItem(item)}</div>))}</div>);
});export default OptimizedList;

6. 页面组件示例 (Admin.jsx)

import { withAuth } from '../components/WithAuth';
import { useFetch } from '../hooks/useFetch';
import OptimizedList from '../components/OptimizedList';const AdminPanel = ({ user }) => {const { data: posts, loading, error } = useFetch('/api/posts');if (loading) return <div>Loading posts...</div>;if (error) return <div>Error: {error}</div>;return (<div><h1>欢迎管理员 {user.name}</h1><h2>文章管理</h2><OptimizedListitems={posts}renderItem={(post) => (<div style={{ padding: '10px', borderBottom: '1px solid #ccc' }}><h3>{post.title}</h3><p>{post.content}</p></div>)}/></div>);
};// 使用高阶组件包裹,要求管理员权限
export default withAuth(AdminPanel, 'admin');

7. 主应用组件 (App.jsx)

// App.jsx
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { UserProvider } from './contexts/UserContext';
import HomePage from './pages/HomePage';
import AdminPage from './pages/AdminPage';
import LoginPage from './pages/LoginPage';
import UserProfilePage from './pages/UserProfilePage';
import ArticleDetailPage from './pages/ArticleDetailPage';const App = () => {return (<UserProvider><Router><Switch><Route path="/" exact component={HomePage} /><Route path="/login" component={LoginPage} /><Route path="/profile" component={UserProfilePage} /><Route path="/admin" component={AdminPage} /><Route path="/articles/:id" component={ArticleDetailPage} /></Switch></Router></UserProvider>);
};export default App;

8. 登录页面示例 (Login.jsx)

import React, { useState, useContext } from 'react';
import { UserContext } from '../contexts/UserContext';const LoginPage = () => {const { login } = useContext(UserContext);const [username, setUsername] = useState('');const [password, setPassword] = useState('');const handleSubmit = (e) => {e.preventDefault();// 假设我们直接使用固定的用户名和密码登录if (username === 'admin' && password === 'admin123') {login({ username, role: 'admin' });} else {alert('Invalid credentials');}};return (<form onSubmit={handleSubmit}><input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" /><input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" /><button type="submit">Login</button></form>);
};export default LoginPage;

9. 文章详细页 (ArticleDetailPage.jsx)

展示文章的详细信息,点击文章标题进入。

// pages/ArticleDetailPage.jsx
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useFetch } from '../hooks/useFetch';const ArticleDetailPage = () => {const { id } = useParams();const { data: article, loading, error } = useFetch(`/api/articles/${id}`);if (loading) return <p>Loading...</p>;if (error) return <p>Error: {error.message}</p>;return (<div><h1>{article.title}</h1><p>{article.content}</p></div>);
};export default ArticleDetailPage;

10. 用户个人资料页 (UserProfilePage.jsx)

用户可以更新个人资料。

// pages/UserProfilePage.jsx
import React, { useState, useContext } from 'react';
import { UserContext } from '../contexts/UserContext';const UserProfilePage = () => {const { user, logout } = useContext(UserContext);const [username, setUsername] = useState(user.username);const handleSave = () => {// 在这里可以将更新后的用户名保存到后端console.log('Username updated:', username);};return (<div><h1>User Profile</h1><input type="text" value={username} onChange={(e) => setUsername(e.target.value)} /><button onClick={handleSave}>Save</button><button onClick={logout}>Logout</button></div>);
};export default UserProfilePage;

11. 分页功能 (HomePage.jsx)

文章列表实现分页功能,每页显示一定数量的文章。

// pages/HomePage.jsx
import React, { useState } from 'react';
import { useFetch } from '../hooks/useFetch';
import { ArticleList } from '../components/ArticleList';const HomePage = () => {const [page, setPage] = useState(1);const { data: articles, loading, error } = useFetch(`/api/articles?page=${page}`);if (loading) return <p>Loading...</p>;if (error) return <p>Error: {error.message}</p>;return (<div><ArticleList articles={articles} /><button onClick={() => setPage(page - 1)} disabled={page === 1}>Previous</button><button onClick={() => setPage(page + 1)}>Next</button></div>);
};export default HomePage;

11. 防抖(useDebouncedFetch.js)

用于处理防抖操作,避免频繁请求。

// hooks/useDebouncedFetch.js
import { useState, useEffect } from 'react';export const useDebouncedFetch = (url, delay) => {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);useEffect(() => {const timer = setTimeout(() => {const fetchData = async () => {try {const response = await fetch(url);const result = await response.json();setData(result);} catch (error) {setError(error);} finally {setLoading(false);}};fetchData();}, delay);return () => clearTimeout(timer);}, [url, delay]);return { data, loading, error };
};

相关文章:

React 高级教程

使用 React 高级组件&#xff08;HOC&#xff09;实现的完整项目示例&#xff0c;包含权限控制、数据加载状态处理、性能优化等常见高级功能。创建一个简单的博客系统: // 项目结构&#xff1a; src/ |-- components/ | |-- ArticleList.jsx | |-- Article.jsx | |-- He…...

基于Qt 和微信小程序的用户管理系统:WebSocket + SQLite 实现注册与登录

目录 一. 概要 二. 技术栈 三. 系统功能设计 3.1 功能模块 3.2 数据表设计 四. 具体实现 4.1 Qt 服务端 4.1.1 初始化 WebSocket 服务器 4.1.2 用户管理界面 4.2 微信小程序端 4.2.1 注册功能 4.2.2 登录功能 五. 运行效果 六. 源码下载 一. 概要 在物联网和智能设备…...

在CT107D单片机综合训练平台上实现外部中断控制LED闪烁

引言 在单片机开发中&#xff0c;外部中断是一个非常重要的功能&#xff0c;它可以让单片机在检测到外部信号变化时立即做出响应。本文将详细介绍如何在CT107D单片机综合训练平台上使用外部中断来控制LED灯的闪烁。我们将使用两种不同的方式来实现这一功能&#xff1a;一种是在…...

HTML之JavaScript使用JSON

HTML之JavaScript使用JSON JSON(JavaScript Object Notation)是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。JSON是JavaScript对象的字符串表示法&#xff0c;它使用文本表示一个js对象的信息&#xff0c;可以将json字符串转换…...

算法很美笔记(Java)——树

性质 树 上面的性质因为两个结点由一条边连成 结点数目越多&#xff0c;算法复杂度越高 二叉树 结构 层次遍历 利用队列&#xff0c;弹一个&#xff0c;加N个&#xff08;队列里弹出一个元素&#xff0c;就把这个元素的所有孩子加进去&#xff09; 具体来说&#xff1a;指…...

SQL面试题4:相互关注问题

引言 在社交媒体和各类社区平台蓬勃发展的当下&#xff0c;用户之间的关系网络成为了平台运营和数据分析的关键部分。相互关注作为一种重要的社交关系&#xff0c;不仅反映了用户之间的紧密程度&#xff0c;还对平台的社交生态、内容传播等方面有着深远影响。本文将聚焦于 SQL…...

ArcGIS基础知识之ArcMap基础设置——ArcMap选项:常规选项卡设置及作用

作为一名 GIS 从业者,ArcMap 是我们日常工作中不可或缺的工具。对于初学者来说,掌握 ArcMap 的基础设置是迈向 GIS 分析与制图的第一步。今天,就让我们一起深入了解 ArcMap 选项中常规选项卡的各个设置,帮助大家更好地使用这款强大的软件。 在 ArcMap 中,常规选项卡是用户…...

jvm 线程监控调试

文章目录 前言一、使用JDK工具转储线程文件(如jstack)1. 找到Java进程的PID:2. 使用jstack生成线程转储文件:3.验证生成的线程转储文件:二、分析文件1.使用在线工具进行分析上传thread-dump文件,等待解析完成2.查看分析结果总结前言 提示:使用jdk自带工具转储线程监控文…...

25、深度学习-自学之路-卷积神经网络基于MNIST数据集的程序展示

import keras #添加Keraskuimport sys,numpy as np from keras.utils import np_utilsimport osfrom keras.datasets import mnist print("licheng&#xff1a;""20"\n) np.random.seed(1)(x_train,y_train),(x_test,y_test) mnist.load_data() #第一次…...

【C++】解锁<list>的正确姿势

> &#x1f343; 本系列为初阶C的内容&#xff0c;如果感兴趣&#xff0c;欢迎订阅&#x1f6a9; > &#x1f38a;个人主页:[小编的个人主页])小编的个人主页 > &#x1f380; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 > ✌️ &#x1f91e; &#x1…...

Qt中的事件

写一个 可以拖动的按钮 DraggablePushButton.h 头文件 #ifndef DRAGGABLEPUSHBUTTON_H #define DRAGGABLEPUSHBUTTON_H#include <QPushButton> #include <QMouseEvent>class DraggablePushButton : public QPushButton {Q_OBJECTpublic:explicit DraggablePushBu…...

变化检测相关论文可读list

一些用得上的&#xff1a; 遥感变化检测常见数据集https://github.com/rsdler/Remote-Sensing-Change-Detection-Dataset/ 代码解读&#xff1a;代码解读 | 极简代码遥感语义分割&#xff0c;结合GDAL从零实现&#xff0c;以U-Net和建筑物提取为例 NeurIPS2024: https://mp.w…...

Ansible中playbook的变量

变量 playbook的变量有以下几种 在playbook中用户自定义的变量远程主机中由Ansible收集的变量在文件模板中使用的上述两种变量把任务结果作为一个变量使用&#xff0c;叫注册变量用户在执行playbook时&#xff0c;通过命令行传入的变量&#xff0c;叫做额外变量 在playbook中…...

亚信安全正式接入DeepSeek

亚信安全致力于“数据驱动、AI原生”战略&#xff0c;早在2024年5月&#xff0c;推出了“信立方”安全大模型、安全MaaS平台和一系列安全智能体&#xff0c;为网络安全运营、网络安全检测提供AI技术能力。自2024年12月DeepSeek-V3发布以来&#xff0c;亚信安全人工智能实验室利…...

相似性图相关性重构网络用于无监督跨模态哈希

《Similarity Graph-correlation Reconstruction Network for unsupervised cross-modal hashing》 摘要1. 引言2. 相关工作2.1. 监督跨模态哈希方法2.2. 无监督跨模态哈希方法 3. 方法论3.1 问题定义3.2 特征提取3.3 模态内关系图构建3.4. 局部关系图重置3.5. 跨模态关系图构建…...

【Bug】属性 PackageVersion 应在所有目标框架中具有单个值,但却具有以下值

文章目录 问题问题代码原因解决处理Bug的具体步骤 问题 严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) NU1105 无法读取“x”的项目信息: 属性 PackageVersion 应在所有目标框架中具有单个值&#xff0c;但却具有以下值: 1.0.0, 1.0.5 x (net8.0-android), x (net8.…...

C++ Primer 类型转换

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…...

【CS61A 2024秋】Python入门课,全过程记录P7(Week13 Macros至完结)【完结撒花!】

文章目录 关于新的问题更好的解决方案Week13Mon Macros阅读材料Lab 11: Programs as Data, MacrosQ1: WWSD: QuasiquoteQ2: If ProgramQ3: Exponential PowersQ4: Repeat Wed SQL阅读材料Disc 11: MacrosQ1: Mystery MacroQ2: Multiple AssignmentQ3: Switch Optional Contest:…...

SSH隧道+Nginx:绿色通道详解(SSH Tunnel+nginx: Green Channel Detailed Explanation)

SSH隧道Nginx&#xff1a;内网资源访问的绿色通道 问题背景 模拟生产环境&#xff0c;使用两层Nginx做反向代理&#xff0c;请求公网IP来访问内网服务器的网站。通过ssh隧道反向代理来实现&#xff0c;重点分析一下nginx反代的基础配置。 实验环境 1、启动内网服务器的tomca…...

LabVIEW用户界面设计原则

在LabVIEW开发中&#xff0c;用户界面&#xff08;UI&#xff09;设计不仅仅是为了美观&#xff0c;它直接关系到用户的操作效率和体验。一个直观、简洁、易于使用的界面能够大大提升软件的可用性&#xff0c;尤其是在复杂的实验或工业应用中。设计良好的UI能够减少操作错误&am…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...