React hook

Hook

这篇文章我们来聊一聊的React中的hook?

1.什么是Hook呢?

hooks我们可以简单地理解为React为我们提供的一些api,来供我们使用。如果大家学习过Vue.js3,就会发现Vue3提供的api与React中的hook中api使用方式非常类似。

下面来看看hook中的api有哪些?

2.Hook api

2.1 useState

这个api的作用主要是设置数据 || 绑定数据的! 它的参数主要有两种形式 : 数据 || 回调函数

绑定数据用法:

父组件

import React, { useState } from 'react'
import Home from './component/Home'
export default function App() {
  let [data, setData] = useState(["吕德华", "东星耀阳"])
  console.log(data);
  const handleData = (val) => {
    let arr = [val, ...data]
    setData(arr)
  }
  return (
    <>
      <p>App组件</p>
      {data}
      <button onClick={() => handleData("北幕")}>CLICK ME</button>
      <hr />
      <Home data={data} setData={setData}></Home>
    </>
  )
}

子组件

import React from 'react'

export default function Home({ data, setData }) {
    const handleData = (val) => {
        let arr = [val, ...data]
        console.log(arr);
        setData(arr)
    }

    return (
        <>
            <p>Home组件数据</p>
            <hr />
            {data}
            <button onClick={() => handleData("大厂")}>CLICK ME</button>
        </>
    )
}

绑定回调函数用法:
import React, { useState } from 'react'
import Home from './component/Home'
export default function App() {
  let [data, setData] = useState(() => {
    return ['吕德华']
  })
  console.log(data);
  const handleData = (val) => {
    let arr = [val, ...data]
    setData(arr)
  }
  return (
    <>
      <p>App组件</p>
      {data}
      <button onClick={() => handleData("北幕")}>CLICK ME</button>
      <hr />
      <Home data={data} setData={setData}></Home>
    </>
  )
}

这个时候的绑定的值就是return返回的值,回调函数的用法主要是用来处理一些数据结构和数据类型,然后再进行返回。

2.2 useRef

用于获取dom节点,class类实例对象。注意是一一对应的用法:创建一个使用一个。

import React, { useState, useRef } from 'react'
import Home from './component/Home'
export default function App() {
  const myRef = useRef()
  let [data, setData] = useState(() => {
    return ['吕德华']
  })
  console.log(data);
  const handleData = (val) => {
    console.log(myRef.current.innerText);
    let arr = [val, ...data]
    setData(arr)
  }
  return (
    <>
      <p ref={myRef}>App组件</p>
      {data}
      <button onClick={() => handleData("北幕")}>CLICK ME</button>
      <hr />
      <Home data={data} setData={setData}></Home>
    </>
  )
}

2.3 useContext

主要用于跨组件传值。

步骤

创建context ===> 包裹要传值的组件 = => useContext()

传值的那个组件

import React from 'react'
import Home from './component/Home'
import { createContext } from 'react'
export const context = createContext()
export default function App() {
  return (
    <context.Provider value={{ msg: '1234' }}>
      <Home></Home>
    </context.Provider>
  )
}

接受值的那个组件

import React from 'react'
import Home from './component/Home'
import { createContext } from 'react'
export const context = createContext()
export default function App() {
  return (
    <context.Provider value={{ msg: '1234' }}>
      <Home></Home>
    </context.Provider>
  )
}

如果想要规范的写法,可以另设一个文件夹,专门用来写hooks的这些用法。

2.4 useCallback

这个api主要用于性能优化,用于存储函数不会被重新创建。函数组件重新执行的时候会重新创建内部所有的函数。

  1. 存储函数不会被删除

  2. 防止子组件进行不必要渲染, 父组件传递函数不要进行重新创建传递

    useCallback(callback,依赖项)

    callback 返回的储存函数

​ 依赖项 选择缓存方式,

​ 1. 不写,每次函数重新执行都会重新创建改函数

​ 2. [],初始时执行一次,后续不在更新,就没有办法获取到新的useState的数据

        3. [数据] => 选择性更新(选择性重新创建)  => 选择的数据发变化,函数重新创建(该回调函数仅在某个依赖项改变时才会更新) , 获取新的useState的数据     返回的是函数,第一个函数不会执行
应用场景

一个函数里面不可能只有一个数据,当函数里面有多个数据的时候。可根据某个依赖数据选择是否对应改变,而不用每次改变一个数据就重新创建所有的函数,这样会十分地浪费性能。

import React, { useCallback, useState } from 'react'
let set = new Set();
export default function App() {
  let [data, setData] = useState(0)
  let [qwe, setqwe] = useState(100)
  const handleData = useCallback(() => {
    setData(data + 1)
  })
  set.add(handleData)
  const handleQwe = useCallback(() => {
    setqwe(qwe + 1)
  })
  set.add(handleQwe)
  console.log(set);
  return (
    <>
      data--{data}
      <hr />
      qwe--{qwe}
      <hr />


      <button onClick={handleData}>点我处理data</button>
      <button onClick={handleQwe}>点我处理qwe</button>


    </>
  )
}

2.5 useMemo

用于存储数据的(计算得出的值进行存储)

useMemo(callback,依赖项) 返回数据

依赖项 选择缓存方式,

​ 1. 不写,每次函数重新执行都会重新创建改函数

​ 2. [],初始时执行一次,后续不在更新,就没有办法获取到新的useState的数据

​ 3. [数据] => 选择性更新(选择性重新创建) => 选择的数据发变化,函数重新创建,获取新的useState的数据

用法和useCallback一模一样,这里不做过多演示!

2.6 useReducer

它是加强版的useState,本质还是用于存储数据的,操作数据的。但是在这个里面,他处理的逻辑可以更复杂。相当于一个小型的仓库,用来存放一些复杂的逻辑!!!

const [state,dispatch]=useReducer(reducer,init)

reducer(prevState,action)

第一个参数是上一次的状态,第二个参数是行为。

例如代码如下:

import React, { useReducer } from 'react'
let init = {
  num: 0
}
let reducer = (prevState, actions) => {
  //第一个参数:
  //初始的时候,是init里面的函数。后面是上一次返回的参数
  // actions是行为  触发的行为
  // console.log(prevState.num);
  // console.log(actions);
  if (actions.type === 'add') {
    return { num: prevState.num + 1 }
  }

  if (actions.type === 'sub') {
    return { num: prevState.num - 1 }
  }
}

export default function App() {
  let [{ num }, dispatch] = useReducer(reducer, init)
  // console.log(num, dispatch);

  return (
    <div>
      <h1>App计数器----{num}</h1>
      <button onClick={() => dispatch({ type: 'add' })}>ADD</button >
      <button onClick={() => dispatch({ type: "sub" })}>SUBLINE</button>
    </div>
  )
}

使用useReducer的好处:不用写多个函数,传入类型即可,可以处理一些较为复杂的逻辑!!!

2.7 useEffect

首先,我们要知道ajax在react中是什么时候发送请求。通过实验,我们发现,如果我们在函数组件中使用ajax发送请求的话,这个发送请求将会无限循环地执行下去!下面我们来看一段代码:

import React, { useState } from 'react'
import axios from 'axios'
export default function App() {
    let [arr, setArr] = useState([])
    axios.get("http://jsonplaceholder.typicode.com/posts?userId=2&name=kaola&age=18")
        .then(({ data }) => {
            setArr(data)
            console.log('11111');
        })
    return (
        <div>
            {
                arr.map(item => {
                    return (
                        <p key={item.id}>{item.title}</p>
                    )
                })
            }
        </div>
    )
}

这段代码,我们打开控制台就会发现,他在一直无限循环地打印。因为,setArr会重新更新视图,而重新更新视图又要重新执行这个函数组件。

使用方法:

useEffect(callback,依赖项) 用于处理副作用;  
        callback

        依赖项
                1. 不写,每次函数重新执行都会重新创建
                2. [],初始时执行一次,后续不在执行
                3. [数据] => 选择性执行  =>
                        根据选择的数据发变化,重新执行, 
                        初始时会执行

这个第三项的典型用法,就是作为分页的时候,将数据传过去。

import React, { useState, useEffect } from 'react'
import axios from 'axios'
export default function App() {
    let [arr, setArr] = useState([])
    useEffect(() => {
        axios.get("http://jsonplaceholder.typicode.com/posts?userId=2&name=kaola&age=18")
            .then(({ data }) => {
                setArr(data)
                console.log('11111');
            })
    }, [])

    return (
        <div>
            {
                arr.map(item => {
                    return (
                        <p key={item.id}>{item.title}</p>
                    )
                })
            }
        </div>
    )
}

这样的话,就只会打印一次。

3.自定义hook

什么是自定义hook?

​ 顾名思义,自定义hook就是我们自己定制的函数。

自定义hook有什么作用呢?

​ 复用react,抽离react。

  • 限制特点:

  • 1.自定义函数(hook)必须以use开头,将会以hook文件进行解析。这里有个命名规范。函数组件首字母大写表示组件,小写是函数,use是hooks。

    2.hook只能在函数组件和use函数中使用

    3.hooks方法函数组件和use函数中进行使用

    4.函数内部的最顶层使用,不能在循环,条件判断,子函数等使用

分离之后的代码

hooks/handleChoose.js

import { useState } from "react"

export const useHandleData = (value) => {
        //value在这里只能传递数组
        let [data, setData] = useState(value)
        let handleAdd = (value1) => {
                setData(data.filter((item) => item === value1))
        }

        let handleDel = (value1) => {
                setData(data.filter((item) => {
                        return item !== value1
                }))
        }
        return [data, handleAdd, handleDel]
}

App.js

import React from 'react'
import { useHandleData } from './hooks/hookChoose'
export default function App() {
    let [arr, handleAdd, handleDel] = useHandleData(['朱雀', 'YY', '路遥', '锦鲤'])

    return (
        <>
            <h1>App组件记事本</h1>
            {
                arr.map(item => {
                    return <li key={item}>喜欢:{item}--<button onClick={() => handleAdd(item)}>确定</button><button onClick={() => handleDel(item)}>删除</button></li>
                }
                )
            }

        </>
    )
}

分离之前的代码:

import React, { useState } from 'react'
export default function App() {
    let [arr, setArr] = useState(['朱雀', 'YY', '路遥', '锦鲤'])
    let handleAdd = (value) => {
        setArr(arr.filter((item) => item === value))
    }
    let handleDel = (value) => {
        setArr(arr.filter((item) => {
            return item !== value
        }))
    }
    return (
        <>
            <h1>App组件记事本</h1>
            {
                arr.map(item => {
                    return <li key={item}>喜欢:{item}--<button onClick={() => handleAdd(item)}>确定</button><button onClick={() => handleDel(item)}>删除</button></li>
                }
                )
            }

        </>
    )
}

显然,分离后比分离前逻辑更加清晰!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值