程序员书籍笔记 程序员书籍笔记
  • HTML
  • CSS
  • JavaScript
  • 前端知识
  • Vue
  • MarkDown
  • git
  • Node.js
  • Linux
  • 51单片机
  • 四级
  • 第一学期课程
  • 操作系统
  • 计算机网络
  • 数据结构
  • 计算机组成原理
  • HTML5
  • Electron
  • 日记便签
  • 前端导航
GitHub (opens new window)
  • HTML
  • CSS
  • JavaScript
  • 前端知识
  • Vue
  • MarkDown
  • git
  • Node.js
  • Linux
  • 51单片机
  • 四级
  • 第一学期课程
  • 操作系统
  • 计算机网络
  • 数据结构
  • 计算机组成原理
  • HTML5
  • Electron
  • 日记便签
  • 前端导航
GitHub (opens new window)
  • HTML

  • CSS

  • JavaScript

  • GO

  • 正则表达式

  • java

  • TypeScript

  • react

    • 组件
    • this指向
    • 受控组件
    • 组件通信
    • 案例及同级组件通信
    • Props和插槽
    • 生命周期
    • 路由
    • 极客PC项目
    • 组件复用
    • hooks
    • hooks更多用法
      • Hooks 更多用法
      • useRef ()
      • useContext ()
      • React-memo ()
        • 浅层对比
      • useCallback ()
      • useMemo ()
        • 避免昂贵的计算(计算属性)
    • Reudx
    • todo案例
    • react函数组件
    • 基本使用
  • 前端知识

  • jQuery

  • Python

  • C和C++

  • 前端和后端
  • react
yuadh
2022-08-02
目录

hooks更多用法

# Hooks 更多用法

# useRef ()

使用场景:在 React 中进行 DOM 操作时,用来获取 DOM

作用:返回一个带有 current 属性的可变对象,通过该对象进行 DOM 操作了

const inputRef = useRef(null)
1

使用

const App = () => {
  const inputRef = useRef(null)
  const add = () => {
    console.log(inputRef.current.value)
  }
  return (
    <section className="todoapp">
      <input type="text" placeholder="请输入内容" ref={inputRef} />{' '}
      <button onClick={add}>添加</button>
    </section>
  )
}
1
2
3
4
5
6
7
8
9
10
11
12

注意:useRef 不仅仅可以用于操作 DOM , 还可以操作组件

# useContext ()

使用场景:跨组件共享通信

Context 作用:实现跨组件传递数据,而不必在每个级别手动传递 props,简化组件之间的数据传递过程

const Context = createContext(defaultValue)
const value = useContext(conText)
1
2

Context 对象包含了两个组件

  • <Context.Provider value> 通过 value 属性提供数据
  • <Context.Consumer> 通过 render-props 模式,在 JSX 中获取Context 提供的数据

在函数组件中,获取 Context 中的值,需需要配合 Context 一起使用而 useContext 和 Context.Consumer 的区别在于:获取数据的位置不同

示例

import React, { useState, useContext } from 'react'
const Context = React.createContext()
const App = () => {
  const [color, setColor] = useState('red')
  return (
    <Context.Provider value={color}>
      <div>
        <h1>我是根组件</h1>
        <div>颜色:{color}</div>
        <button onClick={() => setColor('yellow')}>修改</button>
        <Father></Father>
      </div>
    </Context.Provider>
  )
}

const Father = () => {
  return (
    <div>
      <h3>我是父组件</h3>
      <Child></Child>
    </div>
  )
}

const Child = () => {
  const color = useContext(Context)
  return (
    <div>
      <h5>我是子组件--{color}</h5>
    </div>
  )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# React-memo ()

使用场景:在父组件的状态更新的时候,子组件就会无条件的一起更新

渲染过程

  • 子组件 props 变化时更新过程:组件代码执行 -> JSX Diff(配合虚拟 DOM) -> 渲染(变化后的内容)
  • 子组件无变化更新过程:代码组件执行 -> JSX Diff (配合虚拟DOM)

为了提升性能,优化不必要的无变化子组件更新,这种情况就可以使用 React.memo 高阶组件

import { useState } from 'react'
import ReactDOM from 'react-dom'

const Child2 = ({ count }) => {
  console.log('Child2 子组件代码执行了')
  return <div style={{ backgroundColor: '#abc' }}>子组件2:{count}</div>
}

const Child1 = () => {
  console.log('Child1 子组件代码执行了')
  return <div style={{ backgroundColor: '#def' }}>子组件1</div>
}

const App = () => {
  const [count, setCount] = useState(0)

  return (
    <div style={{ backgroundColor: 'pink', padding: 10 }}>
      <h1>计数器:{count}</h1>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <hr />

      {/* 子组件 */}
      <Child1 />
      <br />
      <Child2 count={count} />
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

此示例,在子组件2更新时, 子组件1也会执行更新

memo 作用:记忆上一次的更新渲染结果,在 props 没有变化时复用该结果,避免函数不必要的更新

使用示例

import { useState, memo } from 'react' //导入
const Child2 = memo(({ count }) => {
  console.log('Child2 子组件代码执行了')
  return <div style={{ backgroundColor: '#abc' }}>子组件2:{count}</div>
})

const Child1 = memo(() => {
  console.log('Child1 子组件代码执行了')
  return <div style={{ backgroundColor: '#def' }}>子组件1</div>
})
1
2
3
4
5
6
7
8
9
10
  • 参数:需要被记忆的组件,不必要更新的组件
  • 返回值: React 记住的 Child 组件

原理:通过检查对比更新前后 props 是否相同,来决定是否复用上一次的渲染结果

注意: 不是所有的组件都适用 memo,需要经常更新渲染的组件使用 memo 性能反而会降低

# 浅层对比

默认情况下,React.memo 只会对更新前后的 props 进行浅对比

也就是说,对于对象类型的 prop 来说,只会比较引用(地址)

import { useState, memo } from 'react'
import ReactDOM from 'react-dom'

const Child2 = memo(({ count }) => {
  console.log('Child2 子组件代码执行了')
  return <div style={{ backgroundColor: '#abc' }}>子组件2:{count}</div>
})

const Child1 = memo(({ obj }) => {
  console.log('Child1 子组件代码执行了')
  return (
    <div style={{ backgroundColor: '#def' }}>
      子组件1 id:{obj.id} name:{obj.name} age:{obj.age}
    </div>
  )
})

const App = () => {
  const [count, setCount] = useState(0)
  const obj = {
    name: 'yd',
    id: 11,
    age: 22,
  }
  return (
    <div style={{ backgroundColor: 'pink', padding: 10 }}>
      <h1>计数器:{count}</h1>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <hr />
      {/* 子组件 */}
      <Child1 obj={obj} />
      <br />
      <Child2 count={count} />
    </div>
  )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

此处传入的参数为 引用数据类型 ,所以在会浅层的对比地址是否发生变化所以在每次更新组件时,创建的 obj 的地址是不同的所以在更新 DOM 也会更新此组件

可以使用 React.memo 的第二个参数手动控制比较

React.memo(Child,function areEqual(prevProps,nextProps){
  return preProps === nextProps
})
1
2
3

如果返回为 true 表示记住不渲染组件,如果返回 false 表示渲染该组件

更好的解决方法

  • useCallback Hook:记住函数的引用,在组件每次更新时返回相同引用的函数。
  • useMemo Hook:记住任意数据(数值、对象、函数等),在组件每次更新时返回相同引用的数据【功能之一】

# useCallback ()

使用场景:在使用 React.memo 时,为了组件每次更新时都能获取到相同引用的函数,就要使用到

作用:记忆传入的回调函数,这个被记住的回调函数会一直生效,知道依赖项发生改变

const memorizedCallback = useCallback(()=>{
  doSomething(a,b)
},[a,b])
1
2
3
  • 第一个参数:需要记忆的回调函数
  • 第二个参数:依赖项数组,用于指定回调函数中依赖到的数据,即使没有依赖项也得传入空数组此时的回调函数会一直生效
  • 返回值:useCallback 记住的回调函数

示例

import { useState, memo, useCallback } from 'react'
import ReactDOM from 'react-dom'

const App = () => {
  const [count, setCount] = useState(0)
  const [money, setMoney] = useState(1000)

  const help = useCallback(() => {
    setCount(count - 1)
  }, [count])
  return (
    <div>
      <h1>计数器</h1>
      <div>豆豆被打了{count}次</div>
      <div>金钱:{money}</div>
      <button onClick={() => setCount(count + 1)}>打豆豆</button>
      <button onClick={() => setMoney(money + 100)}>加钱</button>
      <hr />
      {count < 5 ? <DouDou count={count} help={help}></DouDou> : '豆豆被打死了'}
    </div>
  )
}

const DouDou = memo(({ count, help }) => {
  console.log('豆豆组件渲染')
  return (
    <div>
      <h3>我是豆豆组件{count}</h3>
      <button onClick={help}>续命</button>
    </div>
  )
})

ReactDOM.render(<App />, document.getElementById('root'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# useMemo ()

使用场景:类似于 useCallback ,可以在组件更新期间保持任意数据引用相等,一般用来处理对象类型的数据

作用:记忆任意数据,这个被记住的数据会一直生效,知道依赖项发生改变

const memorizedValue = useMemo(()=>Valus,deps)
1
  • 第一个参数:回调函数,注意该函数会被调用,并通过返回值指定需要被记住的数据
  • 第二个参数:依赖项数组,用于指定回调函数中依赖到的数据
  • 返回值:useMemo 记住的数据

如何选择使用哪一个?

  • 如果处理的是函数,推荐使用 useCallback Hook。
  • 如果处理的是其他数据(比如,对象),推荐使用 useMemo Hook。

模拟useCallback

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。

const help = useCallback(() => {
  setCount(count - 1)
}, [count])



const help = useMemo(() => {
    return () => {
        setCount(count - 1)
    }
}, [count])
1
2
3
4
5
6
7
8
9
10
11

示例

import React, { useState, memo, useMemo } from 'react'

const App = () => {
  const [count, setCount] = useState(5)
  const [money, setMoney] = useState(1000)

  // 记忆的函数=useCallback(函数, [依赖])
  // 只要依赖项不变,这个函数就不会变化,如果依赖项变了,这个函数就会变化
  const help = useMemo(() => {
    return () => {
      setCount(count + 1)
    }
  }, [count])
  return (
    <div>
      <h1>根组件--{count}</h1>
      <div>金钱:{money}</div>
      <button onClick={() => setCount(count - 1)}>打豆豆</button>
      <button onClick={() => setMoney(money + 100)}>挣钱</button>
      <hr />
      {count > 0 ? <DouDou help={help} count={count}></DouDou> : '豆豆被打死了'}
    </div>
  )
}

const DouDou = memo(({ count, help }) => {
  console.log('豆豆更新了')
  return (
    <div>
      <h3>豆豆组件被打了{count}</h3>
      <button onClick={help}>续命</button>
    </div>
  )
})

export default App

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 避免昂贵的计算(计算属性)

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
1
编辑 (opens new window)
上次更新: 2023/02/07, 14:51:48
hooks
Reudx

← hooks Reudx→

Theme by Vdoing | Copyright © 2021-2023 yuadh
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×