REACT学习--钩子剩余部门

[复制链接]
发表于 2025-10-24 05:25:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
useLayouEffect同步实行状态更新

useEffect()是在渲染被绘制到屏幕之后实行的,是异步的,useLayouEffect()是在渲染之后但是在屏幕更新之前,是同步的
大部门环境下我们采取useEffect(),性能更好,但是useEffect内里的操纵须要处置惩罚DOM,而且会改变页面的样式,就须要用useLayoutEffect,否则大概会出现闪屏题目
  1. import { useEffect, useLayoutEffect, useReducer, useState } from "react";
  2. function App(){
  3.     const [msg,setMsg] = useState('hello App')
  4.     useLayoutEffect(()=>{
  5.         for(let i =0;i<100000;i++){
  6.             setMsg('App hello')
  7.         }
  8.     })
  9.     return (
  10.         <div>
  11.             {msg}
  12.         </div>
  13.     )
  14. }
  15. export default App
复制代码
 uselnsertionEffectDOM更新前触发

useInsertionEffect应用场景非常少,由于获取不到DOM元素,以是只在CSS-in-JS 库中才会利用
这是实行的序次:
  1. import { useEffect,useLayoutEffect,useInsertionEffect } from "react"
  2. function App(){
  3.     //触发时机:3 2 1
  4.     useEffect(()=>{
  5.         console.log(1)
  6.     })
  7.     useLayoutEffect(()=>{
  8.         console.log(2)
  9.     })
  10.     useInsertionEffect(()=>{
  11.         console.log(3)
  12.     })
  13.     return (
  14.         <div>
  15.             hello App
  16.         </div>
  17.     )
  18. }
  19. export default App
复制代码
突然出bug了问一下deepseek

 这大唐笔

不祥的预感
起首 验证依赖安装状态
  1. # 进入项目目录
  2. cd /root/NewLife/vite-project
  3. # 检查是否已安装 tailwindcss
  4. ls node_modules | grep tailwindcss
  5. # 如果没有输出结果,执行完整安装
  6. npm uninstall tailwindcss postcss autoprefixer
  7. npm install -D tailwindcss postcss autoprefixer@latest
复制代码
再逼迫重修设置文件
  1. # 删除现有配置文件
  2. rm -f tailwind.config.js postcss.config.js
  3. # 重新初始化配置
  4. npx tailwindcss init -p --full
复制代码
 我错了对不起
  1. import { useEffect,useLayoutEffect,useInsertionEffect, useRef } from "react"
  2. function App(){
  3.     //触发时机:3 2 1
  4.    const ref = useRef(null)
  5.    useInsertionEffect(()=>{
  6.     const style = document.createElement('style')
  7.     style.innerHTML = `
  8.     .box{
  9.         background:red;
  10.         width:100px;
  11.         height:100px
  12.     }
  13.     `
  14.     document.head.appendChild(style)
  15.    })
  16.     return (
  17.         <div>
  18.             hello App
  19.             <div className="box" ref = {ref}>aaaa</div>
  20.         </div>
  21.     )
  22. }
  23. export default App
复制代码
Reducer同一的状态管理聚集

对于拥有很多状态更新逻辑的组件来说,过于分散的变乱大概会令人不知所措,对于这种环境,可以将组件全部状态更新逻辑整合到一个外部函数中,这个函数叫做reducer
Reducer是处置惩罚状态的另一种方式
  1. import { useState } from 'react'
  2. function App() {
  3.   const [list, setList] = useState([
  4.     { id: 1, text: 'aaa' },
  5.     { id: 2, text: 'bbb' },
  6.     { id: 3, text: 'ccc' },
  7.   ])
  8.   const handleAdd = () => {
  9.     setList([...list, { id: 4, text: 'ddd' }])
  10.   }
  11.   const handleEdit = (id) => {
  12.     setList(
  13.       list.map((item) => {
  14.         if (item.id === id) {
  15.           return { ...item, text: 'new' + item.text }
  16.         } else {
  17.           return item
  18.         }
  19.       })
  20.     )
  21.   }
  22.   const handleRemove = (id) => {
  23.     setList(
  24.       list.filter((item) => {
  25.         if (item.id === id) {
  26.           return false
  27.         } else {
  28.           return true
  29.         }
  30.       })
  31.     )
  32.   }
  33.   return (
  34.     <div>
  35.       hello App
  36.       <input type="text" />
  37.       <button onClick={() => handleAdd()}>添加</button>
  38.       <ul>
  39.         {list.map((item) => {
  40.             return(
  41.           <li key={item.id}>
  42.             {item.text}
  43.             <button onClick={() => handleEdit(item.id)}>编辑</button>
  44.             <button onClick={() => handleRemove(item.id)}>删除</button>
  45.           </li>
  46.             )
  47.         })}
  48.       </ul>
  49.     </div>
  50.   )
  51. }
  52. export default App
复制代码
这东西管理起来很贫困,以是最好会集管理
  1. import { useReducer } from 'react'
  2. //由着reducer函数完成外部逻辑的统一处理
  3. function listReducer(state, action) {
  4.   switch (action.type) {
  5.     case 'add':
  6.       return [...state, { id: 4, text: 'dddd' }]
  7.     case 'edit':
  8.       return state.map((item) => {
  9.         if (item.id === action.id) {
  10.           return { ...item, text: 'new' + item.text }
  11.         } else {
  12.           return item
  13.         }
  14.       })
  15.     case 'remote':
  16.       return state.filter((item) => {
  17.         if (item.id === action.id) {
  18.           return false
  19.         } else {
  20.           return true
  21.         }})
  22.   }
  23. }
  24. function App() {
  25.   const [list, dispatch] = useReducer(listReducer, [
  26.     { id: 1, text: 'aaa' },
  27.     { id: 2, text: 'bbb' },
  28.     { id: 3, text: 'ccc' },
  29.   ])
  30.   return (
  31.     <div>
  32.       hello App
  33.       <input type="text" />
  34.       <button onClick={() => dispatch({ type: 'add' })}>添加</button>
  35.       <ul>
  36.         {list.map((item) => {
  37.           return (
  38.             <li key={item.id}>
  39.               {item.text}
  40.               <button onClick={() => dispatch({ type: 'edit', id: item.id })}>
  41.                 编辑
  42.               </button>
  43.               <button onClick={() => dispatch({ type: 'remote', id: item.id })}>
  44.                 删除
  45.               </button>
  46.             </li>
  47.           )
  48.         })}
  49.       </ul>
  50.     </div>
  51.   )
  52. }
  53. export default App
复制代码
reducer还提供了一个immer版本
现在来改造一下
useImmerReducer 是团结了 Immer 库和 React useReducer 的加强型 Hook,专为简化不可变状态更新而筹划。

  1. import { useImmerReducer } from 'use-immer'
  2. //由着reducer函数完成外部逻辑的统一处理
  3. function listReducer(draft, action) {
  4.   switch (action.type) {
  5.     case 'add':
  6.         draft.push({ id: 4, text: 'ddd' })
  7.         break
  8.     case 'edit':
  9.       const value = draft.find((item)=>item.id === action.id)
  10.       value.text = 'new' + value.text
  11.       break
  12.     case 'remote':
  13.         const index = draft.findIndex((item)=>item.id === action.id)
  14.         draft.splice(index,1)
  15.         break
  16.   }
  17. }
  18. function App() {
  19.   const [list, dispatch] = useImmerReducer(listReducer, [
  20.     { id: 1, text: 'aaa' },
  21.     { id: 2, text: 'bbb' },
  22.     { id: 3, text: 'ccc' },
  23.   ])
  24.   return (
  25.     <div>
  26.       hello App
  27.       <input type="text" />
  28.       <button onClick={() => dispatch({ type: 'add' })}>添加</button>
  29.       <ul>
  30.         {list.map((item) => {
  31.           return (
  32.             <li key={item.id}>
  33.               {item.text}
  34.               <button onClick={() => dispatch({ type: 'edit', id: item.id })}>
  35.                 编辑
  36.               </button>
  37.               <button onClick={() => dispatch({ type: 'remote', id: item.id })}>
  38.                 删除
  39.               </button>
  40.             </li>
  41.           )
  42.         })}
  43.       </ul>
  44.     </div>
  45.   )
  46. }
  47. export default App
复制代码
Context向组件深层通报数据

通常来说会通过props将信息从父组件通报到子组件,但是如果必须通过很多中心组件向下通报props,大概在应用中的很多组件须要雷同的信息,通报props会变得非常的冗长和未便
  1. function App(){
  2.     return (
  3.         <div>
  4.             hello App
  5.             <Head count={123}/>
  6.         </div>
  7.     )
  8. }
  9. function Head({count}){
  10.     return(
  11.         <div>
  12.             hello Head
  13.             <Title count={count}/>
  14.         </div>
  15.     )
  16. }
  17. function Title({count}){
  18.     return (
  19.         <div>
  20.             hello Title,{count}
  21.         </div>
  22.     )
  23. }
  24. export default App
复制代码
Context允许父组件向其下层无论多深的任何组件提供信息,而无需通过props显式通报
  1. import { createContext,useContext } from "react"
  2. const Context = createContext()
  3. function App(){
  4.     return (
  5.         <div>
  6.             hello App
  7.             <Context.Provider value={123}>
  8.                 <Head/>
  9.             </Context.Provider>
  10.         </div>
  11.     )
  12. }
  13. function Head({count}){
  14.     return(
  15.         <div>
  16.             hello Head
  17.             <Title count={count}/>
  18.         </div>
  19.     )
  20. }
  21. function Title({count}){
  22.     const value = useContext(Context)
  23.     return (
  24.         <div>
  25.             hello Title,{value}
  26.         </div>
  27.     )
  28. }
  29. export default App
复制代码
如许之后就是可以更方便的通报,如果要通报多个值就用数组大概对象
还可以添加默认值
  1. import { createContext,useContext, useState } from "react"
  2. const Context = createContext(0)
  3. function App(){
  4.     const [count,setCount] = useState(123)
  5.     const handleClick=()=>{
  6.         setCount(count+1)
  7.     }
  8.     return (
  9.         <div>
  10.             hello App
  11.             <button onClick={handleClick}>点击</button>
  12.             <Context.Provider value={count}>
  13.                 <Head/>
  14.             </Context.Provider>
  15.         </div>
  16.     )
  17. }
  18. function Head({count}){
  19.     return(
  20.         <div>
  21.             hello Head
  22.             <Title count={count}/>
  23.         </div>
  24.     )
  25. }
  26. function Title({count}){
  27.     const value = useContext(Context)
  28.     return (
  29.         <div>
  30.             hello Title,{value}
  31.         </div>
  32.     )
  33. }
  34. export default App
复制代码
Reducer共同Context实现共享状态管理

Reducer可以整合组件的状态更新逻辑,Context可以将信息深入通报给其他组件,可以组合利用他们共同管理一个复杂页面的状态(兄弟状态共享)
存在更复杂的状态管理,可以采取三套方案,Redux,Mobx,Zustand等
ListContent,jsx:
  1. function ListContent(){
  2.     return(
  3.         <ul>
  4.         {
  5.             list.map((item)=> {
  6.              return(
  7.              <li key={item.id}>{item.text}
  8.              <button onClick={()=>listDispatch({type:'edit',id:item.id})}>编辑</button>
  9.              <button onClick={()=>listDispatch({type:'remove',id:item.id})}>删除</button>
  10.              </li>
  11.             )
  12.         })}
  13.     </ul>
  14.     )
  15. }
  16. export default ListContent
复制代码
ListHead.jsx:
  1. import { useContext } from 'react'
  2. import {ListDispatchContext} from './ListProvider.jsx'
  3. function ListHead(){
  4.     const listDispatch = useContext(ListDispatchContext)
  5.     return(
  6.         <>
  7.             <input type="text" /><button onClick={()=>listDispatch({type:'add'})}>添加</button>
  8.         </>
  9.     )
  10. }
  11. export default ListHead
复制代码
ListProvider.jsx:
  1. import {useReducer,createContext} from 'react'
  2. const ListContext = createContext()
  3. const ListDispatchContext = createContext()
  4. function listReducer(draft, action) {
  5.     switch (action.type) {
  6.       case 'add':
  7.           draft.push({ id: 4, text: 'ddd' })
  8.           break
  9.       case 'edit':
  10.         const value = draft.find((item)=>item.id === action.id)
  11.         value.text = 'new' + value.text
  12.         break
  13.       case 'remote':
  14.           const index = draft.findIndex((item)=>item.id === action.id)
  15.           draft.splice(index,1)
  16.           break
  17.     }
  18.   }
  19. function ListProvider({children}){
  20.     const [list,listDispatch] = useReducer(listReducer,[
  21.         {id:1,text:'aaa'},
  22.         {id:2,text:'bbb'},
  23.         {id:3,text:'ccc'},
  24.     ])
  25.     return(
  26.         <ListContext.Provider value={list}>
  27.             <ListDispatchContext.Provider value={listDispatch}>
  28.                 {children}
  29.             </ListDispatchContext.Provider>
  30.         </ListContext.Provider>
  31.     )
  32. }
  33. export default ListProvider
复制代码
Reducer共同Context实现共享状态管理.jsx:
  1. import ListContent from './ListContent'
  2. import ListHead from './ListHead'
  3. import ListProvider from './ListProvider'
  4. function App() {
  5.   return (
  6.     <div>
  7.       hello App
  8.       <ListProvider>
  9.         <ListHead />
  10.         <ListContent />
  11.       </ListProvider>
  12.     </div>
  13.   )
  14. }
  15. export default App
复制代码
reducer管理.jsx:
  1. import { useImmerReducer } from 'use-immer'
  2. //由着reducer函数完成外部逻辑的统一处理
  3. function listReducer(draft, action) {
  4.   switch (action.type) {
  5.     case 'add':
  6.         draft.push({ id: 4, text: 'ddd' })
  7.         break
  8.     case 'edit':
  9.       const value = draft.find((item)=>item.id === action.id)
  10.       value.text = 'new' + value.text
  11.       break
  12.     case 'remote':
  13.         const index = draft.findIndex((item)=>item.id === action.id)
  14.         draft.splice(index,1)
  15.         break
  16.   }
  17. }
  18. function App() {
  19.   const [list, dispatch] = useImmerReducer(listReducer, [
  20.     { id: 1, text: 'aaa' },
  21.     { id: 2, text: 'bbb' },
  22.     { id: 3, text: 'ccc' },
  23.   ])
  24.   return (
  25.     <div>
  26.       hello App
  27.       <input type="text" />
  28.       <button onClick={() => dispatch({ type: 'add' })}>添加</button>
  29.       <ul>
  30.         {list.map((item) => {
  31.           return (
  32.             <li key={item.id}>
  33.               {item.text}
  34.               <button onClick={() => dispatch({ type: 'edit', id: item.id })}>
  35.                 编辑
  36.               </button>
  37.               <button onClick={() => dispatch({ type: 'remote', id: item.id })}>
  38.                 删除
  39.               </button>
  40.             </li>
  41.           )
  42.         })}
  43.       </ul>
  44.     </div>
  45.   )
  46. }
  47. export default App
复制代码
memo在props稳定环境下跳过重新渲染
  1. import { useState } from "react"
  2. function Head(){
  3.     return(
  4.         <div>
  5.             hello Head,{Math.random()}
  6.         </div>
  7.     )
  8. }
  9. function App(){
  10.     const [count,setCount] = useState(0)
  11.     const handleClick = ()=>{
  12.         setCount(count+1)
  13.     }
  14.     return(
  15.         <div>
  16.             hello App
  17.             <button onClick={handleClick}>点击</button>
  18.             <Head />
  19.         </div>
  20.     )
  21. }
  22. export default App
复制代码
子组件会重新渲染吗?
会的
memo是在props没改变的时间跳过渲染,就可以办理count都没变但是Head还在变的题目
  1. import { useState,memo } from "react"
  2. const Head = memo(function Head(){
  3.     return(
  4.         <div>
  5.             hello Head,{Math.random()}
  6.         </div>
  7.     )
  8. })
  9. function App(){
  10.     const [count,setCount] = useState(0)
  11.     const handleClick = ()=>{
  12.         setCount(count+1)
  13.     }
  14.     return(
  15.         <div>
  16.             hello App
  17.             <button onClick={handleClick}>点击</button>
  18.             <Head />
  19.         </div>
  20.     )
  21. }
  22. export default App
复制代码
useMemo对盘算效果举行缓存
  1. import { useState } from "react";
  2. import { memo } from "react";
  3. const Head = memo(function Head(){
  4.     return(
  5.         <div>hello Head,{Math.random()}</div>
  6.     )
  7. })
  8. function App(){
  9.     const [count,setCount] = useState(0)
  10.     const [msg,setMsg]=useState('hello react')
  11.     const list = [msg.toLowerCase(),msg.toUpperCase()]
  12.     const handleClick =()=>{
  13.         setCount(count + 1)
  14.     }
  15.     return (
  16.         <div>
  17.             hello App
  18.             <button onClick={handleClick}>点击</button>
  19.             <Head list={list}/>
  20.         </div>
  21.     )
  22. }
  23. export default App
复制代码
这个照旧会发生改变的,由于地点差异,就算是一样的数组也改变了,他以为是差异的
我们如果想要不让它变
就可以用useMEmo
  1. import { useMemo, useState } from "react";
  2. import { memo } from "react";
  3. const Head = memo(function Head(){
  4.     return(
  5.         <div>hello Head,{Math.random()}</div>
  6.     )
  7. })
  8. function App(){
  9.     const [count,setCount] = useState(0)
  10.     const [msg,setMsg]=useState('hello react')
  11.     const list = useMemo(()=>[msg.toLowerCase(),msg.toUpperCase()],[msg])
  12.     const handleClick =()=>{
  13.         setCount(count + 1)
  14.     }
  15.     return (
  16.         <div>
  17.             hello App
  18.             <button onClick={handleClick}>点击</button>
  19.             <Head list={list}/>
  20.         </div>
  21.     )
  22. }
  23. export default App
复制代码
useCallback对函数举行缓存

useMemo的一种特例写法
  1. import { useMemo, useState } from "react";
  2. import { memo } from "react";
  3. const Head = memo(function Head(){
  4.     return(
  5.         <div>hello Head,{Math.random()}</div>
  6.     )
  7. })
  8. function App(){
  9.     const [count,setCount] = useState(0)
  10.     const [msg,setMsg]=useState('hello react')
  11.     // const fn=()=>{
  12.     //     console.log(count+1)
  13.     // }
  14.     const fn = useMemo(()=>()=>{},[msg])
  15.     const handleClick =()=>{
  16.         setCount(count + 1)
  17.     }
  18.     return (
  19.         <div>
  20.             hello App
  21.             <button onClick={handleClick}>点击</button>
  22.             <Head fn={fn}/>
  23.         </div>
  24.     )
  25. }
  26. export default App
复制代码
如许利用回调函数也不会变,也可以引入useCallback
  1. import { useMemo, useState,useCallback } from "react";
  2. import { memo } from "react";
  3. const Head = memo(function Head(){
  4.     return(
  5.         <div>hello Head,{Math.random()}</div>
  6.     )
  7. })
  8. function App(){
  9.     const [count,setCount] = useState(0)
  10.     const [msg,setMsg]=useState('hello react')
  11.     // const fn=()=>{
  12.     //     console.log(count+1)
  13.     // }
  14.     const fn = useCallback(()=>{console.log(msg)},[msg])
  15.     const handleClick =()=>{
  16.         setCount(count + 1)
  17.     }
  18.     return (
  19.         <div>
  20.             hello App
  21.             <button onClick={handleClick}>点击</button>
  22.             <Head fn={fn}/>
  23.         </div>
  24.     )
  25. }
  26. export default App
复制代码
就写到这吧嘻嘻嘻嘻西邮元哲来了
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表