React - Hook API 使用(函数组件中使用 React 特性)

  1. Hook 是React 16.8.0版本增加的新特性/新语法
  2. 可以在函数组件中使用 state 以及其他的 React 特性
  3. HOOK API: https://react.docschina.org/docs/hooks-intro.html

一. 为什么要使用 HOOK?

  • React的组件创建方式,一种是类组件,一种是函数组件。
  • 函数组件相比较类组件,具有以下特点:
    (1)函数组件没有状态
    (2)函数组件没有生命周期
    (3)函数组件没有this
  • 这就说明函数组件,只能做UI展示的功能,涉及到状态的管理与切换,就不得不用类组件或者redux。
  • 在这种情况下,如果想使用函数组件编写一个完整的功能,就可以使用 HOOKS

二. HOOK 概念

  1. Hook 是React 16.8.0版本增加的新特性/新语法
  2. 可以在函数组件中使用 state 以及其他的 React 特性

三. HOOK 用法

1. useState

使函数组件也可以有 state 状态, 并进行状态数据的读写操作。

1.1 使用方法

import { useState } from "react";

const [state, setState] = useState(initState);
  • initState: useState 参数
    在初始渲染期间,指定state值在内部作缓存
  • [state, setState]: useState 返回值,包含两个元素的数组,
    第一个参数:为内部当前的state状态值,
    第二个参数:为更新state状态值的函数

1.2 setState 两种写法

  1. 第一种写法

    setState(newState);
    

    参数为 非函数值直接指定新的状态值,内部用其覆盖原来的状态值

  2. 第二种写法

    setState(state => {
      // state : 原本的state值
      return newState
    });
    

    参数为函数,接收原本的状态值返回新的状态值,内部用其覆盖原来的状态值

1.3 setState 实例

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

export default function Demo() {
  const [count, setCount] = useState(0);
  function add1() {
    setCount(count + 1);
  }
  function add2() {
    // count : 原本的state值
    setCount((count) => {
      return count + 2;
    });
  }
  return (
    <div>
      <h2>当前数值:{count}</h2>
      <button onClick={add1}>+1</button>
      <button onClick={add2}>+2</button>
    </div>
  );
}

2. useEffect

在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
可以用来更好的处理副作用,比如 添加订阅、设置定时器、接口请求 以及执行其他包含副作用的操作

2.1 使用方法

import { useEffect } from "react";

useEffect(
  () => {
    // 在此可以执行任何带副作用操作
    return () => { // 在组件卸载前执行
      // 在此做一些收尾工作, 比如清除定时器/取消订阅等
    };
  },
  [stateValue],// 如果指定的是[], 回调函数只会在第一次render()后执行
);

可以把 useEffect Hook 看做如下三个函数的组合:

  • componentDidMount()
  • componentDidUpdate()
  • componentWillUnmount()

2.2 useEffect 实例

src/index.js 暴露 root

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { BrowserRouter } from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
export default root;
import React from "react";
import { useState, useEffect } from "react";
import root from "../../index"; //引入root路径

export default function Demo() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    // 定时器
    let timer = setInterval(() => {
      setCount((count) => count + 1);
    }, 1000);
    return () => {
      // 清除定时器
      clearInterval(timer);
    };
  }, []);
  function unMount() {
    root.unmount();
  }
  return (
    <div>
      <h2>当前数值:{count}</h2>
      <button onClick={unMount}>卸载组件</button>
    </div>
  );
}

3. useRef

可以在函数组件中存储/查找组件内的标签或任意其它数据
作用:保存标签对象,功能与React.createRef()一样

3.1 使用方法

import { useRef } from "react";

const refContainer = useRef(initValue);

3.2 useRef 实例

import React from "react";
import { useRef } from "react";

export default function Demo() {
  const myRef = useRef();
  function showInputValue() {
    console.log(myRef.current.value);
  }
  return (
    <div>
      <input ref={myRef} type="text" />
      <button onClick={showInputValue}>打印输入框信息</button>
    </div>
  );
}

4. useContext

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。

4.1 使用方法

const value = useContext(MyContext);

4.2 useContext 实例

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

// 创建一个createContext对象
const CountContext = createContext();
const { Provider } = CountContext;

export default function A() {
  const [user] = useState({
    name: "tom",
    age: 18,
  });
  return (
    <div>
      <h2>A组件</h2>
      <h4>姓名:{user.name}</h4>
      <Provider value={user}>
        <B />
      </Provider>
    </div>
  );
}

function B() {
  return (
    <div>
      <h2>B组件</h2>
      <C />
    </div>
  );
}

function C() {
  // 使用 useContext 接收 A组件的参数
  const value = useContext(CountContext);
  return (
    <div>
      <h2>D组件</h2>
      <h4>
        接收到的A组件数值为:{value.name}{value.age}
      </h4>
    </div>
  );
}

5. useMemo

5.1 使用方法

  1. 它仅会在某个依赖项改变时才重新计算 memoized 值,有助于避免在每次渲染时都进行高开销的计算。
  2. 简而言之,useMemo是用来缓存计算属性的。
const memoizedValue = useMemo(callback, array);
  • 返回一个 memoized 值。
  • callback 是一个函数用于处理逻辑。
  • array 控制useMemo重新执⾏的数组,array改变时才会重新执行useMemo

5.2 useMemo 实例

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

export default function Page1() {
  const [num, setNum] = useState(0);
  // 使用 useMemo 根据 num 值计算新值
  const memoNum = useMemo(() => {
    return num * 2;
  }, [num]);
  return (
    <div>
      <div>当前数值:{num}</div>
      <div>当前数值 * 2 后的新值:{memoNum}</div>
      <button onClick={() => { setNum(num + 1) }}> +1 </button>
    </div>
  );
}

四. 一个 Hook 组件实例

类组件 对比 函数组件
实现 state 状态修改、定时器、输入框信息打印、组件卸载

  1. 类组件 实现

    src/index.js 暴露 root

    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App";
    import { BrowserRouter } from "react-router-dom";
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(
      <BrowserRouter>
        <App />
      </BrowserRouter>
    );
    export default root;
    
    import React, { Component } from "react";
    import { createRef } from "react";
    import root from "../../index";//引入root路径
    export default class index extends Component {
      state = {
        count: 0,
        name: "tom",
      };
      myRef = createRef();
      componentDidMount() {
        this.timer = setInterval(() => {
          this.setState({
            count: this.state.count + 1,
          });
        }, 1000);
      }
      componentWillUnmount() {
        clearInterval(this.timer);
      }
    
      increment = () => {
        this.setState((state) => {
          return {
            count: state.count + 1,
          };
        });
      };
      updateName = () => {
        this.setState({
          name: "小明",
        });
      };
      unMount = () => {
        root.unmount();
      };
      showInputValue = () => {
        console.log(this.myRef.current.value);
      };
      render() {
        return (
          <div>
            <h4>数值为:{this.state.count}</h4>
            <button onClick={this.increment}>+1</button>
            <h4>名字:{this.state.name}</h4>
            <button onClick={this.updateName}>改名</button>
            <br />
            <br />
            <button onClick={this.unMount}>卸载组件</button>
            <br />
            <br />
            <input ref={this.myRef} type="text" />
            <button onClick={this.showInputValue}>打印输入框信息</button>
          </div>
        );
      }
    }
    
  2. 函数组件 实现

    src/index.js 暴露 root

    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App";
    import { BrowserRouter } from "react-router-dom";
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(
      <BrowserRouter>
        <App />
      </BrowserRouter>
    );
    export default root;
    
    import { useState, useEffect, useRef } from "react";
    import root from "../../index";//引入root路径
    function Index() {
      const [count, setCount] = useState(0);
      const [name, setName] = useState("tom");
      const myRef = useRef();
      useEffect(() => {
        let timer = setInterval(() => {
          setCount((count) => count + 1);
        }, 1000);
        return () => {
          clearInterval(timer);
        };
      }, []);
      function increment() {
        // setCount(count + 1);// 第一种写法
        setCount((count) => {
          return count + 1;
        });
      }
      function updateName() {
        setName("小明");
      }
      function unMount() {
        root.unmount();
      }
      function showInputValue() {
        console.log(myRef.current.value);
      }
      return (
        <div>
          <h4>数值为:{count}</h4>
          <button onClick={increment}>+1</button>
          <h4>名字:{name}</h4>
          <button onClick={updateName}>改名</button>
          <br />
          <br />
          <button onClick={unMount}>卸载组件</button>
          <br />
          <br />
          <input ref={myRef} type="text" />
          <button onClick={showInputValue}>打印输入框信息</button>
        </div>
      );
    }
    
    export default Index;
    
  3. 组件实现效果图
    在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值