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

钩子项目 -- 实战案例品购物车

嘻嘻

startTransition方法及并发模式

React18之前,渲染是一个单一的、不间断的、同步的事务,一旦渲染开始,就不能被中断

React 18引入并发模式,它允许你将标记更新作为一个transitions,这会告诉React它们可以被中断执行,这样可以把紧急的任务先更新,不紧急的任务后更新

 选择高亮:

import { useState } from "react";

function List({query}){
    const items = []
    const word = 'hello world'
    if(query !== '' && word.includes(query)){
        const arr = word.split(query)
        for(let i=0;i<100;i++){
            items.push(<li key={i}>{arr[0]}<span style={{color:'red'}}>{query}</span>{arr[1]}</li> )
        }
    }
    else{
        for(let i = 0;i<100;i++){
            items.push( <li key={i}>{word}</li> )
        }
    }
    return (
        <ul>
            {items}
        </ul>
    )
}

function App(){
    const [search,setSearch] = useState('')
    const [query,setQuery] = useState('')
    const handleChange = (e)=>{
        //紧急
        setSearch(e.target.value)
        //紧急
        setQuery(e.target.value)
    }
    return(
        <div>
            hello App
            <input type="text" value={search} onChange={handleChange}/>
            <List query={query}/>
        </div>
    )
}
export default App

 

 但是它是等所有的都加载完在渲染

有些任务不是和紧急,所以就以缓缓

import { useState ,startTransition } from "react";

function List({query}){
    const items = []
    const word = 'hello world'
    if(query !== '' && word.includes(query)){
        const arr = word.split(query)
        for(let i=0;i<100;i++){
            items.push(<li key={i}>{arr[0]}<span style={{color:'red'}}>{query}</span>{arr[1]}</li> )
        }
    }
    else{
        for(let i = 0;i<100;i++){
            items.push( <li key={i}>{word}</li> )
        }
    }
    return (
        <ul>
            {items}
        </ul>
    )
}

function App(){
    const [search,setSearch] = useState('')
    const [query,setQuery] = useState('')
    const handleChange = (e)=>{
        //紧急
        setSearch(e.target.value)
        //紧急
        startTransition(()=>{
            setQuery(e.target.value)
        })
    }
    return(
        <div>
            hello App
            <input type="text" value={search} onChange={handleChange}/>
            <List query={query}/>
        </div>
    )
}
export default App

 useTransition与useDeferredValue

useTransition是一个让你在不阻塞UI的情况下来更新状态的React Hook,返回一个状态值表示过渡任务的等待状态,以及一个启动该过渡任务的函数

useDeferredValue接受一个值,并返回该值的新副本,该副本将推迟到更紧急的更新之后


import { useState,useTransition } from "react";

function List({query}){
    const items = []
    const word = 'hello world'
    if(query !== '' && word.includes(query)){
        const arr = word.split(query)
        for(let i=0;i<10000;i++){
            items.push(<li key={i}>{arr[0]}<span style={{color:'red'}}>{query}</span>{arr[1]}</li> )
        }
    }
    else{
        for(let i = 0;i<10000;i++){
            items.push( <li key={i}>{word}</li> )
        }
    }
    return (
        <ul>
            {items}
        </ul>
    )
}

function App(){
    const [search,setSearch] = useState('')
    const [query,setQuery] = useState('')
    const [pending,startTransition] = useTransition()
    const handleChange = (e)=>{
        //紧急
        setSearch(e.target.value)
        //紧急
        startTransition(()=>{
            setQuery(e.target.value)
        })
    }
    return(
        <div>
            hello App
            <input type="text" value={search} onChange={handleChange}/>
            {pending&& <div>loading...</div> }
            <List query={query}/>
        </div>
    )
}
export default App

刚才输入法和谷歌浏览器都卡了

也是神人了

这样做完之后有loading效果

 

还有就是我想说分析一大堆给出一个我不需要的结果的deepseek是屑

问了下豆包马上就解决了。。。

还是穿换着用吧

 另一个钩子的使用:

import { useState,useDeferredValue } from "react";

function List({query}){
    const items = []
    const word = 'hello world'
    if(query !== '' && word.includes(query)){
        const arr = word.split(query)
        for(let i=0;i<10000;i++){
            items.push(<li key={i}>{arr[0]}<span style={{color:'red'}}>{query}</span>{arr[1]}</li> )
        }
    }
    else{
        for(let i = 0;i<10000;i++){
            items.push( <li key={i}>{word}</li> )
        }
    }
    return (
        <ul>
            {items}
        </ul>
    )
}

function App(){
    const [search,setSearch] = useState('')
    //得到对应 search一样的值,只不过是一个延迟的副本
    const [query,setQuery] = useDeferredValue(search)
    const [pending,startTransition] = useTransition()
    const handleChange = (e)=>{
        setSearch(e.target.value)
    }
    return(
        <div>
            hello App
            <input type="text" value={search} onChange={handleChange}/>
            {pending&& <div>loading...</div> }
            <List query={query}/>
        </div>
    )
}
export default App

 useld生成唯一ID值

 useId是一个React Hook,可以生成传递给无障碍属性的唯一ID

import React, { useId } from 'react';

function MyInput(){

    const password = useId()

    return (
        <>
         <label>
            密码:
            <input type="password" 
            aria-describedby={ 'password'+password}/>
         </label>
         <p id={'password'+password}>
             密码至少应该包含18个字符
         </p>
        </>
    )
}
function App(){
    return(
        <div>
            hello App
            <MyInput/>
        </div>
    )
}
export default App

React还有非常不常用的两个钩子:useDebugValue,useSyncExternalStore

在用自定义Hook中打印一些信息用,还是在下载了一些React工具的前提下

知道你不常用了退下吧

实战案例:商品购物车

 老实说要下载安装一个axios的库

阿贾克斯。。。

npm i axios

 

购物车.jsx:

import './购物车.css'
import axios from 'axios'
import { useImmer } from 'use-immer'
import { act, useEffect,memo,useCallback} from 'react'

const Item = memo(function Item({
  id,
  name,
  price,
  number,
  active,
  handleAdd,
  handleNumberChange,
}) {
  return (
    <li className={active ? 'active' : ' '}>
      <h3>{name}</h3>
      <p>单价:{price}</p>
      <p>
        数量:
        <span className="remove" onClick={() => handleNumberChange(id, -1)}>
          -
        </span>
        <span>{number}</span>
        <span className="add" onClick={() => handleNumberChange(id, +1)}>
          +
        </span>
      </p>
      <div className="cartbtn" onClick={() => handleAdd(id)}>
        {active ? '取消购买' : '添加购物车'}
      </div>
    </li>
  )
}
)
function Cart() {
  const [list, setList] = useImmer([])
  const all = list.filter((item)=>item.active).reduce((init,item)=> init + item.number*item.price,0)
  useEffect(() => {
    axios.get('./cartData.json').then((res) => {
      setList(res.data.list.map((item) => ({ ...item, active: false })))
    })
  }, [])

  const handleAdd = useCallback ((id) => {
    setList((draft) => {
      const value = draft.find((item) => item.id === id)
      value.active = !value.active
    })
  },[])

  const handleNumberChange = useCallback((id, num) => {
    setList((draft) => {
      const value = draft.find((item) => item.id === id)
      if (value.number === 0 && num < 0) {
        return
      }
      value.number += num
    })
  },[])

  return (
    <div className="cart">
      <ul>
        {list.map((item) => (
          <Item
            key={item.id}
            {...item}
            handleAdd={handleAdd}
            handleNumberChange={handleNumberChange}
          />
        ))}
      </ul>
      <ul>
        <Item />
      </ul>
      <div className="all">
        总金额:<span>{all}</span>元
      </div>
    </div>
  )
}

export default Cart

购物车.css:

*{margin: 0; padding: 0;}
li{ list-style: none;}
.cart{ width: 700px; margin: 30px auto;}
.cart ul{ overflow: hidden;}
.cart li{ width: 100px; border: 5px gray dotted; border-radius: 20px; padding: 20px; float: left; margin:10px;}
.cart .remove,.cart .add{ cursor: pointer;}
.cart .cartbtn{ font-size:14px; text-align: center; background: red; color: white; padding: 3px; border-radius: 5px; margin-top: 10px; cursor: pointer;}
.cart li.active{ border-color:red;}
.cart li.active .cartbtn{ background-color: skyblue;}
.cart .all{ text-align: center; margin: 20px 0;}

购物车静态布局.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    *{margin: 0; padding: 0;}
    li{ list-style: none;}
    .cart{ width: 700px; margin: 30px auto;}
    ul{ overflow: hidden;}
    li{ width: 100px; border: 5px gray dotted; border-radius: 20px; padding: 20px; float: left; margin:10px;}
    .remove, .add{ cursor: pointer;}
    .cartbtn{ font-size:14px; text-align: center; background: red; color: white; padding: 3px; border-radius: 5px; margin-top: 10px; cursor: pointer;}
    li.active{ border-color:red;}
    li.active .cartbtn{ background-color: skyblue;}
    .all{ text-align: center; margin: 20px 0;}
  </style>
  <script src="https://unpkg.com/react@18.2.0/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
</head>
<body>
  <div id="app"></div>
  <script type="text/babel">
    let app = document.querySelector('#app');
    let root = ReactDOM.createRoot(app);

    let Cart = () => {
      return (
        <div className="cart">
          <ul>
            <li className="active">
              <h3>香蕉</h3>
              <p>单价:5</p>
              <p>
                数量:
                <span className="remove">-</span>
                <span>1</span>
                <span className="add">+</span>
              </p>
              <div className="cartbtn">取消购买</div>
            </li>
            <li>
              <h3>香蕉</h3>
              <p>单价:5</p>
              <p>
                数量:
                <span className="remove">-</span>
                <span>1</span>
                <span className="add">+</span>
              </p>
              <div className="cartbtn">添加到购物车</div>
            </li>
            <li>
              <h3>香蕉</h3>
              <p>单价:5</p>
              <p>
                数量:
                <span className="remove">-</span>
                <span>1</span>
                <span className="add">+</span>
              </p>
              <div className="cartbtn">添加到购物车</div>
            </li>
            <li>
              <h3>香蕉</h3>
              <p>单价:5</p>
              <p>
                数量:
                <span className="remove">-</span>
                <span>1</span>
                <span className="add">+</span>
              </p>
              <div className="cartbtn">添加到购物车</div>
            </li>
            <li>
              <h3>香蕉</h3>
              <p>单价:5</p>
              <p>
                数量:
                <span className="remove">-</span>
                <span>1</span>
                <span className="add">+</span>
              </p>
              <div className="cartbtn">添加到购物车</div>
            </li>
            <li>
              <h3>香蕉</h3>
              <p>单价:5</p>
              <p>
                数量:
                <span className="remove">-</span>
                <span>1</span>
                <span className="add">+</span>
              </p>
              <div className="cartbtn">添加到购物车</div>
            </li>
          </ul>
          <div className="all">
            总金额:<span>5</span>元
          </div>
        </div>
      );
    }

    let element = (
      <Cart />
    );
    
    root.render(element)

  </script>
</body>
</html>


http://www.kler.cn/a/567120.html

相关文章:

  • 数据库基础三(MySQL数据库操作)
  • leetcode35.搜索插入位置
  • 02内存映射与bmp解码
  • GCM模式在IPSec中的应用
  • Redis持久化方案RDB和AOF
  • C#光速入门的指南
  • 人工智能之数学基础:线性代数中的特殊矩阵
  • 计算机毕业设计Python+DeepSeek-R1大模型游戏推荐系统 Steam游戏推荐系统 游戏可视化 游戏数据分析(源码+文档+PPT+讲解)
  • Linux笔记---一切皆文件
  • AI编程Cursor之高级使用技巧
  • iOS for...in 循环
  • SpringBoot项目启动报错:PathVariable annotation was empty on param 0.
  • thinkphp下的Job队列处理
  • C语言多级指针详解 - 通过实例理解一级、二级、三级指针
  • day01_Java基础
  • 请谈谈 Node.js 中的流(Stream)模块,如何使用流进行数据处理?
  • Windows提权之第三方提权(九)
  • uniapp选中日期移动到中间
  • P8682 [蓝桥杯 2019 省 B] 等差数列--sort()
  • 宝塔webhooks与码云实现自动部署