React学习(二)——状态(数据)与状态修改

   useState

在React中,useState 是一个非常重要的Hook,它允许你在函数组件中添加“状态”(state)。在传统的React类组件中,我们使用this.state来管理和更新组件的状态。然而,在函数组件中,由于它们没有实例,因此我们不能直接使用this.state。这时,useState Hook 就派上了用场。

 在函数组件中,你可以使用useState来声明一个新的状态变量。useState接收一个初始状态值作为参数,并返回一个状态变量数组。数组的第一个元素是当前的状态值,第二个元素是一个用于更新状态的函数

function ExampleComponent() {  // 声明一个新的状态变量,初始值为 0  const [count, setCount] = useState(0);  // 渲染一个按钮,点击时增加计数器的值  return (  <div>  <p>You clicked {count} times</p>  <button onClick={() => setCount(count + 1)}>  Click me  </button>  </div>  );  
}

状态更新是异步的

需要注意的是,React可能会将多个setState调用合并成一个批处理更新,以提高性能。因此,你不应该依赖于setState的立即结果来计算下一个状态。例如,以下代码可能不会按预期工作:

setCount(count + 1);  
console.log(count); // 这可能仍然打印旧的count值

 如果你需要根据前一个状态来计算新的状态,你可以将函数作为setCount参数传递,该函数接收当前的状态值并返回新的状态值

setCount(prevCount => prevCount + 1);

总结

  • useState是React的一个Hook,允许你在函数组件中添加状态。
  • useState接收一个初始状态值作为参数,并返回一个包含当前状态值和更新状态函数的数组。
  • 状态更新可能是异步的,因此你不应该依赖于setState的立即结果。
  • 如果你需要根据前一个状态来计算新的状态,可以将函数作为setState的参数传递。

JSX中使用JS表达式

在JSX中可以通过大括号语法}识别JavaScript中的表达式,比如常见的变量、函数调用、方法调
用等等
1.使用引号传递字符串  2.使用JavaScript变量

3.函数调用和方法调用   4.使用JavaScript对象

//列表渲染
const items = ['Apple', 'Banana', 'Cherry'];  function ListItems() {  return (  <ul>  {items.map((item, index) => (  <li key={index}>{item}</li>  ))}  </ul>  );  
}
//渲染条件内容:
function Greeting(props) {  const isLoggedIn = props.isLoggedIn;  let content;  if (isLoggedIn) {  content = <p>Welcome back!</p>;  } else {  content = <p>Please log in.</p>;  }  return (  <div>  {content}  </div>  );  
}
-------------------------------------------------
function Greeting(props) {  return (  <div>  {props.isLoggedIn ? <p>Welcome back!</p> : <p>Please log in.</p>}  </div>  );  
}

React基础事件绑定与传参

在React中,事件绑定是通过在JSX元素上设置事件处理属性来完成的。这些事件处理属性通常以on开头,后跟事件名称(例如,onClickonChangeonMouseMove等),并且它们的值是一个函数。当特定事件在DOM元素上触发时,该函数将被调用。

import React from 'react';  class ButtonComponent extends React.Component {  handleClick = () => {  alert('Button was clicked!');  }  render() {  return (  <button onClick={this.handleClick}>  Click Me  </button>  );  }  
}  export default ButtonComponent;

 在上面的例子中,ButtonComponent类组件有一个handleClick方法,该方法在按钮被点击时会被调用。我们通过在JSX中的button元素上设置onClick属性,并将handleClick方法作为该属性的值来绑定事件。

请注意,我们在handleClick方法前使用了箭头函数语法(handleClick = () => { ... }),这是类属性(class fields)语法的一部分,它允许我们在类体中直接定义方法箭头函数确保thishandleClick方法内部指向当前的类实例,而不是undefined(在非箭头函数中,如果在类的方法中不使用bindthis通常会指向undefined,除非在构造函数中绑定了this)。

  • 类组件中的方法(Class Component Methods):如果你不使用类属性语法,你也可以在构造函数中绑定方法:
import React from 'react';  class ButtonComponent extends React.Component {  constructor(props) {  super(props);  this.handleClick = this.handleClick.bind(this);  }  handleClick() {  alert('Button was clicked!');  }  render() {  return (  <button onClick={this.handleClick}>  Click Me  </button>  );  }  
}  export default ButtonComponent;

 在这个例子中,我们在构造函数中调用了.bind(this)来确保thishandleClick方法内部指向正确的上下文。

  •  使用Hooks(Function Components with Hooks):在函数组件中,你通常会使用Hooks(如useCallback)来处理事件绑定,以避免在每次渲染时都创建新的函数实例,这可能会导致不必要的性能问题:
import React, { useCallback } from 'react';  function ButtonComponent() {  const handleClick = useCallback(() => {  alert('Button was clicked!');  }, []); // 依赖项数组,因为这里不需要依赖任何props或state,所以为空数组  return (  <button onClick={handleClick}>  Click Me  </button>  );  
}  export default ButtonComponent;

注意,useCallback的第二个参数是一个依赖项数组,它告诉React只有当这些依赖项发生变化时,才需要重新创建回调函数。在这个例子中,我们不需要任何依赖项,所以传递了一个空数组。

  • 箭头函数 :在React组件的JSX中,可以直接使用箭头函数来绑定事件处理函数。但是,这种方式会在每次渲染时都创建一个新的函数实例,这可能会导致性能问题,特别是当在列表中渲染多个元素时。
function MyComponent() {  const handleClick = () => {  console.log('Button clicked!');  };  return (  <button onClick={handleClick}>Click Me</button>  );  
}

B站评论案例 

  1. 渲染评论列表

  2. 删除评论实现

  3. 渲染导航Tab和高亮实现

  4. 评论列表排序功能实现

基础模版

import { useState } from 'react'
import './App.scss'
import avatar from './images/bozai.png'/*** 评论列表的渲染和操作** 1. 根据状态渲染评论列表* 2. 删除评论*/// 评论列表数据
const defaultList = [{// 评论idrpid: 3,// 用户信息user: {uid: '13258165',avatar: '',uname: '周杰伦',},// 评论内容content: '哎哟,不错哦',// 评论时间ctime: '10-18 08:15',like: 88,},{rpid: 2,user: {uid: '36080105',avatar: '',uname: '许嵩',},content: '我寻你千百度 日出到迟暮',ctime: '11-13 11:29',like: 88,},{rpid: 1,user: {uid: '30009257',avatar,uname: '黑马前端',},content: '学前端就来黑马',ctime: '10-19 09:00',like: 66,},
]
// 当前登录用户信息
const user = {// 用户iduid: '30009257',// 用户头像avatar,// 用户昵称uname: '黑马前端',
}/*** 导航 Tab 的渲染和操作** 1. 渲染导航 Tab 和高亮* 2. 评论列表排序*  最热 => 喜欢数量降序*  最新 => 创建时间降序*/// 导航 Tab 数组
const tabs = [{ type: 'hot', text: '最热' },{ type: 'time', text: '最新' },
]const App = () => {return (<div className="app">{/* 导航 Tab */}<div className="reply-navigation"><ul className="nav-bar"><li className="nav-title"><span className="nav-title-text">评论</span>{/* 评论数量 */}<span className="total-reply">{10}</span></li><li className="nav-sort">{/* 高亮类名: active */}<span className='nav-item'>最新</span><span className='nav-item'>最热</span></li></ul></div><div className="reply-wrap">{/* 发表评论 */}<div className="box-normal">{/* 当前用户头像 */}<div className="reply-box-avatar"><div className="bili-avatar"><img className="bili-avatar-img" src={avatar} alt="用户头像" /></div></div><div className="reply-box-wrap">{/* 评论框 */}<textareaclassName="reply-box-textarea"placeholder="发一条友善的评论"/>{/* 发布按钮 */}<div className="reply-box-send"><div className="send-text">发布</div></div></div></div>{/* 评论列表 */}<div className="reply-list">{/* 评论项 */}<div className="reply-item">{/* 头像 */}<div className="root-reply-avatar"><div className="bili-avatar"><imgclassName="bili-avatar-img"alt=""/></div></div><div className="content-wrap">{/* 用户名 */}<div className="user-info"><div className="user-name">jack</div></div>{/* 评论内容 */}<div className="root-reply"><span className="reply-content">这是一条评论回复</span><div className="reply-info">{/* 评论时间 */}<span className="reply-time">{'2023-11-11'}</span>{/* 评论数量 */}<span className="reply-time">点赞数:{100}</span><span className="delete-btn">删除</span></div></div></div></div></div></div></div>)
}export default App
.app {width: 80%;margin: 50px auto;
}.reply-navigation {margin-bottom: 22px;.nav-bar {display: flex;align-items: center;margin: 0;padding: 0;list-style: none;.nav-title {display: flex;align-items: center;width: 114px;font-size: 20px;.nav-title-text {color: #18191c;font-weight: 500;}.total-reply {margin: 0 36px 0 6px;color: #9499a0;font-weight: normal;font-size: 13px;}}.nav-sort {display: flex;align-items: center;color: #9499a0;font-size: 13px;.nav-item {cursor: pointer;&:hover {color: #00aeec;}&:last-child::after {display: none;}&::after {content: ' ';display: inline-block;height: 10px;width: 1px;margin: -1px 12px;background-color: #9499a0;}}.nav-item.active {color: #18191c;}}}
}.reply-wrap {position: relative;
}
.box-normal {display: flex;transition: 0.2s;.reply-box-avatar {display: flex;align-items: center;justify-content: center;width: 80px;height: 50px;}.reply-box-wrap {display: flex;position: relative;flex: 1;.reply-box-textarea {width: 100%;height: 50px;padding: 5px 10px;box-sizing: border-box;color: #181931;font-family: inherit;line-height: 38px;background-color: #f1f2f3;border: 1px solid #f1f2f3;border-radius: 6px;outline: none;resize: none;transition: 0.2s;&::placeholder {color: #9499a0;font-size: 12px;}&:focus {height: 60px;background-color: #fff;border-color: #c9ccd0;}}}.reply-box-send {position: relative;display: flex;flex-basis: 86px;align-items: center;justify-content: center;margin-left: 10px;border-radius: 4px;cursor: pointer;transition: 0.2s;& .send-text {position: absolute;z-index: 1;color: #fff;font-size: 16px;}&::after {position: absolute;width: 100%;height: 100%;background-color: #00aeec;border-radius: 4px;opacity: 0.5;content: '';}&:hover::after {opacity: 1;}}
}
.bili-avatar {position: relative;display: block;width: 48px;height: 48px;margin: 0;padding: 0;border-radius: 50%;
}
.bili-avatar-img {position: absolute;top: 50%;left: 50%;display: block;width: 48px;height: 48px;object-fit: cover;border: none;border-radius: 50%;image-rendering: -webkit-optimize-contrast;transform: translate(-50%, -50%);
}// 评论列表
.reply-list {margin-top: 14px;
}
.reply-item {padding: 22px 0 0 80px;.root-reply-avatar {position: absolute;left: 0;display: flex;justify-content: center;width: 80px;cursor: pointer;}.content-wrap {position: relative;flex: 1;&::after {content: ' ';display: block;height: 1px;width: 100%;margin-top: 14px;background-color: #e3e5e7;}.user-info {display: flex;align-items: center;margin-bottom: 4px;.user-name {height: 30px;margin-right: 5px;color: #61666d;font-size: 13px;line-height: 30px;cursor: pointer;}}.root-reply {position: relative;padding: 2px 0;color: #181931;font-size: 15px;line-height: 24px;.reply-info {position: relative;display: flex;align-items: center;margin-top: 2px;color: #9499a0;font-size: 13px;.reply-time {width: 76px;margin-right: 20px;}.reply-like {display: flex;align-items: center;margin-right: 19px;.like-icon {width: 14px;height: 14px;margin-right: 5px;color: #9499a0;background-position: -153px -25px;&:hover {background-position: -218px -25px;}}.like-icon.liked {background-position: -154px -89px;}}.reply-dislike {display: flex;align-items: center;margin-right: 19px;.dislike-icon {width: 16px;height: 16px;background-position: -153px -153px;&:hover {background-position: -217px -153px;}}.dislike-icon.disliked {background-position: -154px -217px;}}.delete-btn {cursor: pointer;&:hover {color: #00aeec;}}}}}
}.reply-none {height: 64px;margin-bottom: 80px;color: #99a2aa;font-size: 13px;line-height: 64px;text-align: center;
}

完成版本

 import { useState } from 'react'
import './App.scss'
import avatar from './images/bozai.png'
import orderBy from 'lodash/orderBy'/*** 评论列表的渲染和操作** 1. 根据状态渲染评论列表* 2. 删除评论*/// 评论列表数据
const defaultList = [{// 评论idrpid: 3,// 用户信息user: {uid: '13258165',avatar: '',uname: '周杰伦',},// 评论内容content: '哎哟,不错哦',// 评论时间ctime: '10-18 08:15',like: 88,},{rpid: 2,user: {uid: '36080105',avatar: '',uname: '许嵩',},content: '我寻你千百度 日出到迟暮',ctime: '11-13 11:29',like: 88,},{rpid: 1,user: {uid: '30009257',avatar,uname: '黑马前端',},content: '学前端就来黑马',ctime: '10-19 09:00',like: 66,},
]
// 当前登录用户信息
const user = {// 用户iduid: '30009257',// 用户头像avatar,// 用户昵称uname: '黑马前端',
}/*** 导航 Tab 的渲染和操作** 1. 渲染导航 Tab 和高亮* 2. 评论列表排序*  最热 => 喜欢数量降序*  最新 => 创建时间降序*/// 导航 Tab 数组
const tabs = [{ type: 'hot', text: '最热' },{ type: 'time', text: '最新' },
]const App = () => {// 导航 Tab 高亮的状态const [activeTab, setActiveTab] = useState('hot')const [list, setList] = useState(defaultList)// 删除评论const onDelete = rpid => {// 如果要删除数组中的元素,需要调用 filter 方法,并且一定要调用 setList 才能更新状态setList(list.filter(item => item.rpid !== rpid))}// tab 高亮切换const onToggle = type => {setActiveTab(type)let newListif (type === 'time') {// 按照时间降序排序// orderBy(对谁进行排序, 按照谁来排, 顺序)newList = orderBy(list, 'ctime', 'desc')} else {// 按照喜欢数量降序排序newList = orderBy(list, 'like', 'desc')}setList(newList)}return (<div className="app">{/* 导航 Tab */}<div className="reply-navigation"><ul className="nav-bar"><li className="nav-title"><span className="nav-title-text">评论</span>{/* 评论数量 */}<span className="total-reply">{list.length}</span></li><li className="nav-sort">{/* 高亮类名: active */}{tabs.map(item => {return (<divkey={item.type}className={item.type === activeTab ? 'nav-item active' : 'nav-item'}onClick={() => onToggle(item.type)}>{item.text}</div>)})}</li></ul></div><div className="reply-wrap">{/* 发表评论 */}<div className="box-normal">{/* 当前用户头像 */}<div className="reply-box-avatar"><div className="bili-avatar"><img className="bili-avatar-img" src={avatar} alt="用户头像" /></div></div><div className="reply-box-wrap">{/* 评论框 */}<textareaclassName="reply-box-textarea"placeholder="发一条友善的评论"/>{/* 发布按钮 */}<div className="reply-box-send"><div className="send-text">发布</div></div></div></div>{/* 评论列表 */}<div className="reply-list">{/* 评论项 */}{list.map(item => {return (<div key={item.rpid} className="reply-item">{/* 头像 */}<div className="root-reply-avatar"><div className="bili-avatar"><imgclassName="bili-avatar-img"src={item.user.avatar}alt=""/></div></div><div className="content-wrap">{/* 用户名 */}<div className="user-info"><div className="user-name">{item.user.uname}</div></div>{/* 评论内容 */}<div className="root-reply"><span className="reply-content">{item.content}</span><div className="reply-info">{/* 评论时间 */}<span className="reply-time">{item.ctime}</span>{/* 评论数量 */}<span className="reply-time">点赞数:{item.like}</span>{user.uid === item.user.uid && (<spanclassName="delete-btn"onClick={() => onDelete(item.rpid)}>删除</span>)}</div></div></div></div>)})}</div></div></div>)
}export default App

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/361684.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux-笔记 全志平台休眠功能初探

前言 全志平台支持的休眠功能主要包括两种模式&#xff1a;休眠模式和待机模式。这两种模式用于降低设备的功耗&#xff0c;并在需要时快速恢复工作状态。由于平台为T113&#xff0c;所以可以很方便的使用RTC来做唤醒源。唤醒源指的是能够让系统从休眠状态恢复到工作状态的信号…

华为DCN技术:M-LAG

M-LAG&#xff08;Multichassis Link Aggregation Group&#xff09;即跨设备链路聚合组&#xff0c;是一种实现跨设备链路聚合的机制。M-LAG主要应用于普通以太网络、VXLAN和IP网络的双归接入&#xff0c;可以起到负载分担或备份保护的作用。相较于另一种常见的可靠性接入技术…

ArkTS开发系列之Web组件的学习(2.9)

上篇回顾&#xff1a;ArkTS开发系列之事件&#xff08;2.8.2手势事件&#xff09; 本篇内容&#xff1a; ArkTS开发系列之Web组件的学习&#xff08;2.9&#xff09; 一、知识储备 Web组件就是用来展示网页的一个组件。具有页面加载、页面交互以及页面调试功能 1. 加载网络…

ARM架构简明教程

目录 一、ARM架构 1、RISC指令集 2、ARM架构数据类型的约定 2.1 ARM-v7架构数据类型的约定 2.2 ARM-v8架构数据类型的约定 3、CPU内部寄存器 4、特殊寄存器 4.1 SP寄存器 4.2 LR寄存器 4.3 PC寄存器 二、汇编 1、汇编指令&#xff08;常用&#xff09; 2、C函数的…

平凉小果子,平凡中的惊艳味道

平凉美食小果子&#xff0c;这看似平凡的名字背后&#xff0c;藏着无数平凉人的美好回忆。它不仅仅是一种食物&#xff0c;更是一种情感的寄托&#xff0c;一种文化的传承。小果子的制作过程看似简单&#xff0c;实则蕴含着深厚的功夫。选用优质的面粉作为主要原料&#xff0c;…

6毛钱SOT-23封装28V、400mA 开关升压转换器,LCD偏置电源和白光LED应用芯片TPS61040

SOT-23-5 封装 TPS61040 丝印PHOI 1 特性 • 1.8V 至 6V 输入电压范围 • 可调节输出电压范围高达 28V • 400mA (TPS61040) 和 250mA (TPS61041) 内部开关电流 • 高达 1MHz 的开关频率 • 28μA 典型空载静态电流 • 1A 典型关断电流 • 内部软启动 • 采用 SOT23-5、TSOT23…

STL迭代器的基础应用

STL迭代器的应用 迭代器的定义方法&#xff1a; 类型作用定义方式正向迭代器正序遍历STL容器容器类名::iterator 迭代器名常量正向迭代器以只读方式正序遍历STL容器容器类名::const_iterator 迭代器名反向迭代器逆序遍历STL容器容器类名::reverse_iterator 迭代器名常量反向迭…

Flutter TIM 项目实现

目录 1. 服务端API 1.1 生成签名 1.1.1 步骤 第一步:获取签名算法 第二步:查看函数输入输出 第三步:nodejs 实现功能 1.1.2 验证签名 小结 1.2 Rest API 调用 1.2.1 签名介绍 1.2.2 腾讯接口 生成管理员 administrator 签名 包装一个 post 请求函数 查询账号 …

新需求:如何实现一个ShardingSphere分库分表平台

大家好&#xff0c;目前我们正面对一个既具挑战又令人兴奋的任务——构建一套高效、稳定的数据处理系统&#xff0c;特别是一个结合了SpringBoot、ShardingSphere、MyBatisPlus和MySQL技术的综合数据分库分表平台。简单来说&#xff0c;我们要做的就是打造一个能轻松应对大数据…

MMDetection训练自己的数据集coco格式

参考 ​​MMDetection 目标检测 —— 环境搭建和基础使用-CSDN博客 利用labelme制作自己的coco数据集(labelme转coco数据集&#xff09;-CSDN博客 1.下载mmdetection 克隆mmdetection到本地 git clone https://github.com/open-mmlab/mmdetection.git 如果git clone下载的…

【Qt】学习Day1

文章目录 Qt简介创建第一个Qt程序创建过程介绍main函数工程文件头文件控件源文件快捷键按钮控件常用API对象树坐标系 信号和槽自定义信号自定义槽函数触发自定义的信号案例-下课后&#xff0c;老师触发饿了信号&#xff0c;学生响应信号&#xff0c;请客吃饭重载信号连接信号La…

【目标检测】Yolov8 完整教程 | 检测 | 计算机视觉

学习资源&#xff1a;https://www.youtube.com/watch?vZ-65nqxUdl4 努力的小巴掌 记录计算机视觉学习道路上的所思所得。 1、准备图片images 收集数据网站&#xff1a;OPEN IMAGES 2、准备标签labels 网站&#xff1a;CVAT 有点是&#xff1a;支持直接导出yolo格式的标…

PHP师生荣誉管理系统-计算机毕业设计源码10079

目 录 摘要 1 绪论 1.1 研究背景 1.2论文结构与章节安排 2 师生荣誉管理系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.…

AI新热点:边云协同:大模型结合小模型(大小模型联合推理)

背景 AI模型规模不断剧增已是不争的事实。模型参数增长至百亿、千亿、万亿甚至十万亿&#xff0c;大模型在算力推动下演变为人工智能领域一场新的“军备竞赛”。 这种竞赛很大程度推动了人工智能的发展&#xff0c;但随之而来的能耗和端侧部署问题限制了大模型应用落地。2022…

离线安装docker-v26.1.4,compose-v2.27.0

目录 ​编辑 1.我给大家准备好了提取即可 2.安装docker和compose 3.解压 4.切换目录 5.执行脚本 6.卸载docker和compose 7.执行命令 “如果您在解决类似问题时也遇到了困难&#xff0c;希望我的经验分享对您有所帮助。如果您有任何疑问或者想分享您的经历&#xff0c;…

windows10/win11截图快捷键 和 剪贴板历史记录 快捷键

后知后觉的我今天又学了两招&#xff1a; windows10/win11截图快捷键 按 Windows 徽标键‌ Shift S。 选择屏幕截图的区域时&#xff0c;桌面将变暗。 默认情况下&#xff0c;选择“矩形模式”。 可以通过在工具栏中选择以下选项之一来更改截图的形状&#xff1a;“矩形模式”…

计算机组成原理笔记-第1章 计算机系统概论

第一章 计算机系统概论 笔记PDF版本已上传至Github个人仓库&#xff1a;CourseNotes&#xff0c;欢迎fork和star&#xff0c;拥抱开源&#xff0c;一起完善。 该笔记是最初是没打算发网上的&#xff0c;所以很多地方都为了自我阅读方便&#xff0c;我理解了的地方就少有解释&a…

【UE5.3】笔记4-自定义材质蓝图

正常来说&#xff0c;我们都是拿到什么材质用什么材质&#xff0c;那么我们如何去创建自定义的材质呢&#xff1f; 首先&#xff0c;创建MyMaterials文件夹用来存放我们自制的材质&#xff1b; 然后&#xff0c;右键创建一个材质&#xff0c;起个名字&#xff0c;双击打开&am…

springcould-config git源情况下报错app仓库找不到

在使用spring config server服务的时候发现在启动之后的一段时间内控制台会抛出异常&#xff0c;spring admin监控爆红&#xff0c;控制台信息如下 --2024-06-26 20:38:59.615 - WARN 2944 --- [oundedElastic-7] o.s.c.c.s.e.JGitEnvironmentRepository : Error occured …

onlyoffice官方文档中打开文件示例的相关测试

文档地址&#xff1a;https://api.onlyoffice.com/zh/editors/open 开发环境&#xff1a; 后端&#xff1a;zdppy_api开发的一个文档服务前端&#xff1a;vue3开发的客户端 我们在index.html中&#xff0c;引入了文档服务的js文件&#xff1a; <!doctype html> <h…