简单的认识一些常用的Hook

1,为什么需要Hook?

Hook是React 16.8新增的特性,他可以**让我们在不编写class的情况下使用state以及其他的React特性
**(比如生命周期)

1,1不使用hooks

import React, { PureComponent } from 'react';

class App extends PureComponent {
  constructor (props) {
    super(props);
    this.state = {
      message: 'hello World'
    };
  }
  
  render () {
    const { message } = this.state
    return (
        <div>
          {message}
        </div>
    )
  }
}

export default App

在类组件中可以保存原来的状态,但是函数式组件就无法保存自己的状态,当修改值得时候,函数组件也不会重新进行渲染。
,就算可以监听数据的改变,但是也会重新初始化值,达不到修改效果。

Hooks的出现

  • 他可以让我们在不编写class的情况下使用state以及其他的react的特性

使用场景:

  • Hooks的出现基本可以代替我们之前所有使用的class的部分

  • 但是如果是一个旧的项目,你并不需要直接将所有的代码重构为Hooks,因为他完全向下兼容,你可以使用渐进式来使用它(意思是新的组件就用Hooks来编写)

  • Hooks只能在函数组件中使用,不能在类组件中,或者函数组件之外的地方使用

  • 只能在函数组件首部使用Hook

  • 可以自定义Hook使用,但是命名必须要以use开头(useFoo)
    Hooks实现计数器

import { memo, useState } from 'react'

function Counter () {
  // useSate返回的是数组,将useSate进行解构
  const [counter, setCounter] = useState(0)
  return (
      <div>
        <h2>计算总数:{counter}</h2>
        <button onClick={e => setCounter(counter + 1)}>+</button>
        <button onClick={e => setCounter(counter + 1)}>-</button>
      </div>)
}

// 保存状态
export default memo(Counter)

相信通过以上的案例,你已经感受到Hooks的便捷了,接下来,就让我们开始正式学习Hooks

useState

(钩入状态)
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

useEffect

一个函数组件中可以存在多个useEffect(从上到下依次执行)
在这里插入图片描述

 useEffect(() => {
  // 当前传入的回调函数会在组件被渲染完成后,自动执行
  // 比如网络请求/DOM操作/事件监听
  document.title = counter + ''
})

 useEffect(() => {
  // 当前传入的回调函数会在组件被渲染完成后,自动执行
  // 比如网络请求/DOM操作/事件监听
  document.title = counter + ''
  return () => {
    console.log('取消监听redux中数据的变化')
  }
})

数据改变都会导致喊函数组件进行重新加载,这样useEffect就会多次进行不必要的调用,这就造成了性能问题

所以要实现useEffect的性能优化,要限制哪些数据改变才造成useEffect的调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a7nRJbI8-1685603110393)(img_6.png)]

useEffect(() => {
  // 当前传入的回调函数会在组件被渲染完成后,自动执行
  // 比如网络请求/DOM操作/事件监听
  document.title = counter + ''
  // []表示只在组件首次创建的时候进行调用
}, [])

useEffect(() => {
  // 当前传入的回调函数会在组件被渲染完成后,自动执行
  // 比如网络请求/DOM操作/事件监听
  document.title = counter + ''
  // 表示受到counter的影响,counter改变导致页面重新加载会导致useEffect的调用
  // []表示只在组件创建的时候调用一次
}, [counter])

useContext

方便组件之间实现数据共享

先使用createContext创建UserContext

import { createContext } from 'react'

const UserContext = createContext()

export { UserContext }

然后对Counter组件进行数据共享

import React, { memo } from 'react'
import Counter from './Counter'
import { UserContext } from './context'


function App () {
  return (
      <div>
        <UserContext.Provider value={{ name: 'why' }}>
          <Counter/>
        </UserContext.Provider>
      </div>
  )
}

export default memo(App)

然后在Counter组件中接收数据

import { memo, useContext, useEffect, useState } from 'react'
import { UserContext } from './context'

function Counter () {
  // 使用useContext进行数据的获取
  const useValue = useContext(UserContext)
  // useSate返回的是数组,将useSate进行解构
  const [counter, setCounter] = useState(0)
  useEffect(() => {
    // 当前传入的回调函数会在组件被渲染完成后,自动执行
    // 比如网络请求/DOM操作/事件监听
    document.title = counter + ''
    // 表示受到counter的影响,counter改变导致页面重新加载会导致useEffect的调用
  }, [counter])
  console.log(useValue)
  return (
      <div>
        <h2>计算总数:{counter}</h2>
        <button onClick={e => setCounter(counter + 1)}>+</button>
        <button onClick={e => setCounter(counter + 1)}>-</button>
      </div>)
}

// 保存状态
export default memo(Counter)

useReducer

在这里插入图片描述

useCallback

useCallback通常是用来进行性能优化的

当我们需要将一个函数传递给子组件的时候,最好使用useCallback传递给子组件时,将优化后的函数传递给子组件(
当父组件重新渲染时,如果没有使用 useCallback
对函数进行优化,每次渲染都会创建一个新的函数实例,即使函数的内容没有变化。这可能会导致子组件的不必要的重新渲染。)
2.

注意useCallback会出现闭包陷阱

import React, { memo } from 'react'
import Counter from './Counter'
import { UserContext } from './context'


function App () {
  function getName () {
    console.log(123123)
  }
  
  return (
      <div>
        <UserContext.Provider value={{ name: 'why' }}>
          <Counter/>
        </UserContext.Provider>
      </div>
  )
}

export default memo(App)

在这段函数中,数据每发生改变。函数就会被重新创建一次,虽然函数不会被调用,但是每次都会创建一个新的函数,这就会造成性能上的影响

使用useCallback进行优化

import React, { memo, useCallback } from 'react'
import Counter from './Counter'
import { UserContext } from './context'

// useCallback可以限制某个数据改变,getName函数才进行重新加载
function App () {
  const getName = useCallback(function () {
    console.log(123123)
  }, [])
  
  return (
      <div>
        <UserContext.Provider value={{ name: 'why' }}>
          <Counter/>
        </UserContext.Provider>
      </div>
  )
}

export default memo(App)

useMemo

useMemo的作用和useCallback类似,但是useMemo是传入返回值,useCallback是传入函数

import { memo, useMemo } from 'react'

function Sum () {
  let sum = 0
  let getSum = (number) => {
    for (let i = 0; i < number; i++) {
      sum = i + sum
    }
    return sum
  }
  // useMemo返回的是函数的返回值(sum的值是函数的返回值)
  let Sum = useMemo(() => {
    return getSum(100)
  }, [])
  return (
      <div>
        <h2>计算结果:{Sum}</h2>
      </div>
  )
}

export default memo(Sum)

在这里插入图片描述

// 当组件重新渲染的时候,不想让memoizedValue重新创建
const memoizedValue = useMemo(() => ({
  name: 'topu',
  age:20
}),[])

useRef

用于获取组件实列
例如在Sum.jsx组件中

import { memo, useMemo, useRef } from 'react'

function Sum () {
  const sumRef = useRef()
  let sum = 0
  let getSum = (number) => {
    for (let i = 0; i < number; i++) {
      sum = i + sum
    }
    return sum
  }
  let Sum = useMemo(() => {
    return getSum(100)
  }, [])
  let getRef=function (){
    console.log(sumRef.current)
  }
  return (
      <div>
        <h2 ref={sumRef}  onClick={getRef}>计算结果:{Sum}</h2>
      </div>
  )
}

export default memo(Sum)

useLayoutEffect

useLayoutEffect是在渲染内容更新到DOM之前执行,会阻塞DOM的更新,但是useEffect则相反,他不会阻碍DOM更新
官方建议的是使用useEffect,但是在有些特殊场景的时候还是会使用useLayoutEffect

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值