【React】React Hooks

useState

useState 向组件中添加状态变量

image.png
状态是只读的,不可以直接修改

image.png
对于对象类型的状态变量,应该传递一个新的对象来更改

image.png
需要对象展开,并重新赋值,进行增加或者修改。

如果需要删除,则使用 filter。

import { useState } from "react";

function App() {
  const [arr, setArr] = useState([
    { id: 1, name: 'zhangsan' },
    { id: 2, name: 'lisi' },
    { id: 3, name: 'wangwu' }
  ]);
  const content = arr.map((item, index) => {
    return <li key={item.id}>{item.name}</li>
  })
  const deleteVar = () => {
      setArr(arr.filter(item => item.name !== 'zhangsan'))
  }
  return (
    <>
      <ul>
        {content}
      </ul>
      <button onClick={deleteVar}>点击删除zhangsan</button>
    </>
  )
}

export default App

useReducer

让 React 管理多个相对关联的状态数据

import { useReducer } from "react"
// 1. 定义reducer函数,根据不同的action返回不同的状态
function reducer(state, action) {
  switch (action.type) {
    case 'ADD':
      return state + action.payload
    case 'SUB':
      return state - 1
    default:
      return state
  }
}

function App() {
  // 2. 组件中调用 useReducer, 0 是初始化参数
  const [state, dispatch] = useReducer(reducer, 0)
  return (
    <div className="App">
      {state}
      {/* 3. 调用dispatch 产生一个新的状态,匹配事件(可传参) 更新 UI */}
      <button onClick={() => { dispatch({ type: 'ADD', payload:100 }) }}>+</button>
      <button onClick={() => { dispatch({ type: 'SUB' }) }}>-</button>
    </div>
  )
}

export default App;

useRef

  • 进行数据存储 值可以手动修改 不是响应式数据
  • 获取 dom 节点

数据存储

import {useRef, useState} from "react";


function App() {
    const [count, setCount] = useState(0)
    // useState 进行数据存储 值可以手动修改 不是响应式数据
    const preCount = useRef()

    function handleClick() {
        preCount.current = count
        setCount(count + 1)
    }

    return (
        <>
            <p>最新的 count:{count}</p>
            <p>上次的 count:{preCount.current}</p>
            <button onClick={handleClick}>增加count</button>
        </>
    )
}

export default App;

获取 dom 节点

import {useRef, useState} from "react";


function App() {
    const inputRef = useRef(null);

    function handleClick() {
        inputRef.current.focus();
    }

    return (
        <>
            <input ref={inputRef} />
            <button onClick={handleClick}>
                聚焦输入框
            </button>
        </>
    );
}

export default App;

获取组件

import {forwardRef, useImperativeHandle, useRef} from "react";

// 默认子组件不对外开放自身的功能 需要 forwardRef 进行包裹
const Child = forwardRef(function (props, ref) {
    // 暴露给父组件的方法
    useImperativeHandle(ref, () => ({
        myFn: () => {
            console.log('子组件myFn方法')
        }
    }))
    return (
        <div>Child 子组件</div>
    )
})

function App() {
    const childRef = useRef();

    function handleClick() {
        childRef.current.myFn();
    }

    return (
        <>
            <Child ref={childRef}/>
            <button onClick={handleClick}>
                按钮
            </button>
        </>
    );
}

export default App;

useContext

多层级通信 - useContext

官方文档:useContext

import {createContext, useContext, useState} from "react";

function Section({children}) {
    const level = useContext(LevelContent)
    return (
        <section className="section">
            {/*逐渐从上层提供的LevelContext中取值*/}
            <LevelContent.Provider value={level + 1}>
                {/*children 也就是 heading 需要使用 useContext*/}
                {children}
            </LevelContent.Provider>
        </section>
    );
}

function Heading({children}) {
    const level = useContext(LevelContent)
    switch (level) {
        case 1:
            return <h1>{children}</h1>;
        case 2:
            return <h2>{children}</h2>;
        case 3:
            return <h3>{children}</h3>;
        case 4:
            return <h4>{children}</h4>;
        case 5:
            return <h5>{children}</h5>;
        case 6:
            return <h6>{children}</h6>;
        default:
            throw Error('未知的 level:' + level);
    }
}

const LevelContent = createContext(0)

function App() {
    return (
        <Section>
            <Heading>主标题</Heading>
            <Section>
                <Heading>副标题</Heading>
                <Heading>副标题</Heading>
                <Heading>副标题</Heading>
                <Section>
                    <Heading>子标题</Heading>
                    <Heading>子标题</Heading>
                    <Heading>子标题</Heading>
                    <Section>
                        <Heading>子子标题</Heading>
                        <Heading>子子标题</Heading>
                        <Heading>子子标题</Heading>
                    </Section>
                </Section>
            </Section>
        </Section>
    )
}

export default App;

在这里插入图片描述

useEffect

useEffect 在组件中创建由渲染本身引起的操作(如发送 Ajax 请求,更改 DOM 等),即非用户操作。

副作用函数随着依赖项的触发而执行。

image.png
清理副作用一般在组件卸载时执行

useEffect(() =>{
  // 实现副作用逻辑
  return ()=> {
  // 清除副作用逻辑
  }
}, [] )
import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from "react";



function App() {
    const [count, setCount] = useState(0)
    const handleIncrement = ()=>setCount(count + 1)
    const handleDecrement = ()=>setCount(count - 1)
    useEffect(() => {
        console.log('useEffect')
    }, [count]);

    return (
        <>
            <div style={{ padding: 10}}>
                <button onClick={handleIncrement}>+</button>
                <span> {count} </span>
                <button onClick={handleDecrement}>-</button>
            </div>
        </>
    );
}

export default App;

useMemo

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

实例:count1计算斐波那契数列,count2和count1可以触发数值变化。使用memo可以使只有在count1变化时触发斐波那契数列计算函数,而count2变化时不触发斐波那契数列计算函数。


import { useMemo } from "react";
import { useState } from "react";

function fib(n) {
  console.log('计算函数执行')
  if (n < 3) {
    return 1
  }
  return fib(n - 1) + fib(n - 2)
}

function App() {
  const [count1, setCount1] = useState(0)
  const [count2, setCount2] = useState(0)
  console.log('组件重新渲染')
  const result = useMemo(() => {
    return fib(count1)
  }, [count1])
  return (
    <div className="App">
      <button onClick={() => { setCount1(count1 + 1) }}>change count1: {count1}</button>
      <button onClick={() => { setCount2(count2 + 1) }}>change count2: {count2}</button>
      result: {result}
    </div>
  )
}

export default App

image.png

image.png

useCallback

useCallback 缓存函数

import { memo, useCallback, useState} from "react";

// memo 将组件变更为记忆组件
// 如果向组件传入的 prop 没有发生变化 将不会收到外部父组件的影响
const Button = memo(function ({onClick}) {
    console.log('Button渲染了')
    return <button onClick={onClick}>点击触发子组件</button>
})

function App(callback, deps) {
    const [count, setCount] = useState(0)
    // 此时不仅需要 memo 还需要将函数设为useCallback 缓存函数
    // 因为父组件重新渲染 那么handleClick 将被分配一块新的内存地址 和之前的不是同一个函数
    // eslint-disable-next-line react-hooks/exhaustive-deps
    const handleClick = useCallback(() => {
        console.log('点击按钮')
    },[])
    const handleUpdate = () => {
        setCount(count + 1)
    }

    return (
        <>
            <div>
                <p>Count: {count}</p>
                <button onClick={handleUpdate}>点击更新count</button>
                <Button onClick={handleClick}></Button>
            </div>
        </>
    );
}

export default App;

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-04-11 12:32:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-11 12:32:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-11 12:32:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-11 12:32:03       18 阅读

热门阅读

  1. 简单聊聊,聚合支付+分账系统体系的运用

    2024-04-11 12:32:03       13 阅读
  2. 110.平衡二叉树

    2024-04-11 12:32:03       10 阅读
  3. Qt事件机制

    2024-04-11 12:32:03       13 阅读
  4. 3.12 Python赋值运算符

    2024-04-11 12:32:03       10 阅读
  5. KISS 原则和 YAGNI原则

    2024-04-11 12:32:03       14 阅读
  6. 「PHP系列」PHP超级全局变量详解

    2024-04-11 12:32:03       13 阅读
  7. 基于Spring Boot的宠物咖啡馆平台的设计与实现

    2024-04-11 12:32:03       20 阅读
  8. 【Linux】tcpdump P1 - 网络过滤选项

    2024-04-11 12:32:03       17 阅读
  9. git修改某个远端服务器的地址的方式以及4种remote

    2024-04-11 12:32:03       13 阅读
  10. 【报错】Not allowed to load local resource:...

    2024-04-11 12:32:03       13 阅读
  11. STL--容器

    2024-04-11 12:32:03       14 阅读