当前位置: 首页 > 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…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...

sshd代码修改banner

sshd服务连接之后会收到字符串&#xff1a; SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢&#xff1f; 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头&#xff0c…...