前端学习--React(5)

一、useReducer

管理相对复杂的状态数据

定义一个reducer函数,根据action值的不同返回不同的状态

在组件中调用useReducer并传入reducer函数和状态的初始值

事件发生时,通过dispatch函数分派一个对象,即通知reducer具体返回哪个状态对应的操作

import { useReducer } from "react";

function reducer(state, action){
  switch(action.type){
    case 'INC':
      return state + 1
    case 'DEC':
      return state - 1
    case 'SET':
      return action.payload
    default:
      return state
  }
}
function App() {
  const [state, dispatch] = useReducer(reducer, 0)
  return (
    <div className="App">
        <button onClick={()=>dispatch({type:'DEC'})}>-1</button>
        {state}
        <button onClick={()=>dispatch({type:'INC'})}>+1</button>
        {/* 自定义参数 */}
        <button onClick={()=>dispatch({type:'SET', payload:100})}>set 100</button>
    </div>
  );
}

export default App;

 二、useMemo

组件重新渲染时缓存计算的结果

应用场景:消耗比较大的计算

import { useMemo, useState } from "react"
function fib(num){
  console.log('计算函数执行了')
  if ( num < 3 )return 1
  return fib(num - 1) + fib(num - 2)

}
function App() {
  const [count1, setCount1] = useState(0)
  const [count2, setCount2] = useState(0)
  // 如果执行下面注释的代码 即使只有count2变化 计算函数也会执行
  // const result = fib(count1)
  const result = useMemo(() => {
    return fib(count1)
  },[count1])
  console.log('组件重新渲染')
  return (
    <div className="App">
      <button onClick={()=> setCount1(count1 + 1)}>count1:{count1}</button>
      <button onClick={()=> setCount2(count2 + 1)}>count2:{count2}</button>
      {result}
    </div>
  );
}

export default App;

三、React.memo

react组件默认的渲染机制:只要父组件重新渲染子组件就会重新渲染

用法

const MemoComponent = memo(function SomeComponent(props){
    //    ...
})

只有props发生变化时,memo包裹的缓存组件才会重新渲染

import { useState, memo } from "react";
const MemoSon = memo(function Son(props){
  console.log('子组件渲染了')
  return <div>Son</div>
})
function App() {
  const [count, setCount] = useState(0)
  console.log('父组件渲染了')
  return (
    <div className="App">
      <button onClick={() => setCount(count+1)}>+1</button>
      <MemoSon/>
    </div>
  );
}

export default App;

props的比较机制

使用memo缓存组件之后,react会对每一个prop使用Object.is比较新值和老值,返回true表示没有变化

1. 传递一个简单类型的prop prop变化时组件重新渲染

2. 传递一个引用类型的prop 比较的是新值和旧值的引用是否相等 当父组件的函数重新执行时 实际上形成的是新的数组引用

3. 保证引用稳定 -> useMemo 组件渲染的过程中缓存一个值

//情况1 传递简单数据
//点击按钮 子组件会发生变化
import { useState, memo } from "react";
const MemoSon = memo(function Son(props){
  console.log('子组件渲染了')
  return <div>Son{props.count}</div>
})
function App() {
  const [count, setCount] = useState(0)
  console.log('父组件渲染了')
  return (
    <div className="App">
      <button onClick={() => setCount(count+1)}>+1</button>
      <MemoSon count={count}/>
    </div>
  );
}

export default App;
//情况2 传递引用数据
//点击按钮 子组件会发生变化
import { useState, memo } from "react";
const MemoSon = memo(function Son(props){
  console.log('子组件渲染了')
  return <div>Son{props.list}</div>
})
function App() {
  const [count, setCount] = useState(0)
  console.log('父组件渲染了')
  const list = [1,2,3]
  return (
    <div className="App">
      <button onClick={() => setCount(count+1)}>+1</button>
      <MemoSon list={list}/>
    </div>
  );
}

export default App;
//情况3 使用useMemo进行缓存
//子组件不再重新渲染
import { useState, memo, useMemo } from "react";
const MemoSon = memo(function Son(props){
  console.log('子组件渲染了')
  return <div>Son{props.list}</div>
})
function App() {
  const [count, setCount] = useState(0)
  console.log('父组件渲染了')
  const list = useMemo(()=>{
    return [1,2,3]
  }, [])
  return (
    <div className="App">
      <button onClick={() => setCount(count+1)}>+1</button>
      <MemoSon list={list}/>
    </div>
  );
}

export default App;

useCallback

4. 给子组件传递函数

React.memo检测的是props中数据的栈地址是否改变。而父组件重新构建的时候,会重新构建父组件中的所有函数(旧函数销毁,新函数创建,等于更新了函数地址),新的函数地址传入到子组件中被props检测到栈地址更新。也就引发了子组件的重新渲染。

在组件多次渲染的时候缓存函数

使用场景:在往子组件传入了一个函数并且子组件被React.momo缓存了的时候使用

//情况4 传入函数
//点击按钮子组件不会重新渲染 因为使用useCallback缓存
import { useState, memo, useMemo, useCallback } from "react";
const Input = memo(function Input({onChange}){
  console.log('子组件重新渲染')
  return <input type="text" onChange={(e) => onChange(e.target.value)} />
})
function App() {
  const [count, setCount] = useState(0)
  const changeHandler = useCallback((value)=> console.log(value), [])

  return (
    <div className="App">
      <Input onChange={changeHandler}/>
      <button onClick={() => setCount(count+1)}>{count}</button>
      
    </div>
  );
}

export default App;

四、React.forwardRef

import { useRef,forwardRef } from "react";

//如果用下面的函数 sonRef的值是null
// function Son(){
//   return <input type="text"/>
// }
const Son = forwardRef((props, ref)=> {
  return <input type="text" ref={ref}/>
})
function App() {
  const sonRef = useRef(null)
  const showRef = ()=>{
    console.log(sonRef)
  }
  return (
    <div className="App">
      <Son ref={sonRef}/>
      <button onClick={showRef}>focus</button>
    </div>
  );
}

export default App;

相关推荐

  1. 前端学习--React(5)

    2023-12-09 11:28:06       52 阅读
  2. React 学习-5

    2023-12-09 11:28:06       34 阅读
  3. 2024前端面试准备5-React相关

    2023-12-09 11:28:06       34 阅读
  4. 前端学习之——react篇(条件渲染)

    2023-12-09 11:28:06       70 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-09 11:28:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-09 11:28:06       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-09 11:28:06       82 阅读
  4. Python语言-面向对象

    2023-12-09 11:28:06       91 阅读

热门阅读

  1. React查询、搜索类功能的实现

    2023-12-09 11:28:06       59 阅读
  2. ReactJs笔记摘录

    2023-12-09 11:28:06       71 阅读
  3. K8S学习指南(2)-docker的基本使用

    2023-12-09 11:28:06       50 阅读
  4. Solidity学习教程

    2023-12-09 11:28:06       49 阅读
  5. BGP综合

    BGP综合

    2023-12-09 11:28:06      49 阅读
  6. C语言精选——选择题Day40

    2023-12-09 11:28:06       59 阅读
  7. 【力扣100】9.和为k的子数组

    2023-12-09 11:28:06       70 阅读
  8. vue基本运用之常见问题及案例代码

    2023-12-09 11:28:06       53 阅读
  9. error: overloaded function with no contextual type information

    2023-12-09 11:28:06       50 阅读
  10. 爬虫解析-BeautifulSoup-bs4(七)

    2023-12-09 11:28:06       54 阅读
  11. vue+vite+diff.js使用方法

    2023-12-09 11:28:06       51 阅读
  12. npm、yarn常用命令

    2023-12-09 11:28:06       60 阅读
  13. Mac 打不开github解决方案

    2023-12-09 11:28:06       63 阅读
  14. HTML实现每天单词积累

    2023-12-09 11:28:06       35 阅读
  15. 前端知识笔记(三十七)———Django与Ajax

    2023-12-09 11:28:06       53 阅读