15_Hooks

React函数式组件核心——Hooks

Hooks本质上就是一类特殊的函数,它们可以为你的函数型组件(function component)注入一些特殊的功能。

useState

未使用useState的类式组件的案例

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

我们使用hooks后,就变得十分简单

import { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

可以看到,Example变成了一个函数,但这个函数却有自己的状态(count),同时它还可以更新自己的状态(setCount)。

useEffect

在类式组件中,提供了一些声明周期钩子给我们使用,我们可以在组件的特殊时期执行特定的事情,例如 componentDidMount ,能够在组件挂载完成后执行一些东西

在函数式组件中也可以实现,它采用的是 effectHook ,它的语法更加的简单,同时融合了 componentDidUpdata 生命周期,极大的方便了我们的开发

React.useEffect(() => {    console.log('被调用了');})

由于函数的特性,我们可以在函数中随意的编写函数,这里我们调用了 useEffect 函数,这个函数有多个功能

当我们像上面代码那样使用时,它相当于 componentDidUpdata 和 componentDidMount 一同使用,也就是在组件挂载和组件更新的时候都会调用这个函数

它还可以接收第二个参数,这个参数表示它要监测的数据,也就是他要监视哪个数据的变化

当我们不需要监听任何状态变化的时候,我们可以就传递一个空数组,这样它就能当作componentMidMount 来使用

React.useEffect(() => {    console.log('被调用了');}, [])

这样我们只有在组件第一次挂载的时候触发

当然当页面中有多个数据源时,我们也可以选择个别的数据进行监测以达到我们想要的效果

React.useEffect(() => {    console.log('被调用了');}, [count])

这样,我们就只监视 count 数据的变化

当我们想要在卸载一个组件之前进行一些清除定时器的操作,在类式组件中,我们会调用生命周期钩子 componentDidUnmount 来实现,在函数式组件中,我们的写法更为简单,我们直接在 useEffect 的第一个参数的返回值中实现即可

也就是说,第一个参数的函数体相当于 componentDidMount 返回体相当于 componentDidUnmount ,这样我们就能实现在组件即将被卸载时输出一些东西了

实现卸载

function unmount() {    ReactDOM.unmountComponentAtNode(document.getElementById("root"))}

卸载前输出

React.useEffect(() => {    console.log('被调用了');    return () => {        console.log('我要被卸载了');    }}, [count])

因此 useEffect 相当于三个生命周期钩子,componentDidMountcomponentDidUpdatacomponentDidUnmount

useLayoutEffect

useEffect 很类似

它的作用是:在 DOM 更新完成之后执行某个操作

注意:

  • 有 DOM 操作的副作用 hooks
  • 在 DOM 更新之后执行

执行时机在 useEffect 之前,其他都和 useEffect 都相同

useEffect 执行时机在 render 之后

useLayoutEffect 执行时机在 DOM 更新之后

useMemo

作用:让组件中的函数跟随状态更新

注意:优化函数组件中的功能函数

为了避免由于其他状态更新导致的当前函数的被迫执行

第一个参数接收一个函数,第二个参数为数组的依赖列表,返回一个值

const getDoubleNum = useMemo(() => {
    console.log('ddd')
    return 2 * num
}, [num])

useCallback

作用:跟随状态更新执行

注意:

  • 只有依赖项改变时才执行
  • useMemo( () => fn, deps) 相当于 useCallback(fn, deps)

不同点:

  • useCallback 返回的是一个函数,不再是值
  • useCallback 缓存的是一个函数,useMemo 缓存的是一个值,如果依赖不更新,返回的永远是缓存的那个函数
  • 给子组件中传递 props 的时候,如果当前组件不更新,不会触发子组件的重新渲染

useContext

作用:带着子组件渲染

与类似组件中使用的context类似

注意:

  • 上层数据发生改变,肯定会触发重新渲染
  • 我们需要引入 useContext 和 createContext 两个内容
  • 通过 createContext 创建一个 Context 句柄
  • 通过 Provider 确定数据共享范围
  • 通过 value 来分发数据
  • 在子组件中,通过 useContext 来获取数据
import React, { useContext, createContext } from 'react'
const Context = createContext(null)
export default function Hook() {
    const [num, setNum] = React.useState(1)

    return (
        <h1>
            这是一个函数组件 - {num}
        // 确定范围
            <Context.Provider value={num}>
                <Item1 num={num} />
                <Item2 num={num} />
            </Context.Provider>
        </h1>
    )
}
function Item1() {
    const num = useContext(Context)
    return <div>子组件1  {num}</div>
}
function Item2() {
    const num = useContext(Context)
    return <div>子组件2 {num}</div>
}

useReducer

作用:去其他地方借资源

注意:函数组件的 Redux 的操作

  1. 创建数据仓库 store 和管理者 reducer
  2. 通过 useReducer(store,dispatch) 来获取 statedispatch
const store = {
    num: 10
}
const reducer = (state, action) => {
    switch (action.type) {
        case "":
            return
        default:
            return
    }
}
const [state, dispatch] = useReducer(reducer, store)

通过 dispatch 去派发 action

自定义Hooks

放在 utils 文件夹中,以 use 开头命名

例如:模拟数据请求的 Hooks

import React, { useState, useEffect } from "react";
function useLoadData() {
  const [num, setNum] = useState(1);
  useEffect(() => {
    setTimeout(() => {
      setNum(2);
    }, 1000);
  }, []);
  return [num, setNum];
}
export default useLoadData;

减少代码耦合

我们希望 reducer 能让每个组件来使用,我们自己写一个 hooks

自定义一个自己的 LocalReducer

import React, { useReducer } from "react";
const store = { num: 1210 };
const reducer = (state, action) => {
  switch (action.type) {
    case "num":
      return { ...state, num: action.num };
    default:
      return { ...state };
  }
};
function useLocalReducer() {
  const [state, dispatch] = useReducer(reducer, store);
  return [state, dispatch];
}
export default useLocalReducer;

自定义Hooks步骤:

  1. 引入 react 和自己需要的 hook
  2. 创建自己的hook函数
  3. 返回一个数组,数组中第一个内容是数据,第二个是修改数据的函数
  4. 暴露自定义 hook 函数出去
  5. 引入自己的业务组件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傅里叶级数ff

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值