react 中的Hook 用法及介绍

首先,Hook是什么?

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

Hook 是 React 团队在 React 16.8 版本中提出的新特性,在遵循函数式组件的前提下,为已知的 React 概念提供了更直接的 API:props,state,context,refs 以及声明周期,目的在于解决常年以来在 class 组件中存在的各种问题,实现更高效的编写 react 组件。


Hook的使用规则是什么?

Hook 就是 Javascript 函数,使用它们时有两个额外的规则:

只能在 函数外层调用 Hook,不要在循环、条件判断或者子函数中调用。
只能在 React 的函数组件自定义 Hook 中调用 Hook。不要在其他 JavaScript 函数中调用。

Hook的使用!

useState :

useState只能在 React 的函数组件自定义 Hook 中调用 Hook。不要在其他 JavaScript 函数中调用。
const [state, setState] = useState(initialState);
Hook 是什么? Hook 是一个特殊的函数,它可以让你“钩入” React 的特性。例如,useState 是允许你在 React 函数组件中添加 state 的 Hook。稍后我们将学习其他 Hook。
useState :方法的使用

代码如下:

import React, { useState } from 'react';

export default function UseState() {
  const [count, setCount] = useState(0);

  return (
    <div>
       {/* 点击按钮 count-1或+1 */}
      <button onClick={() => setCount(count - 1)}>-</button>
      <button onClick={() => setCount(count + 1)}>+</button>
       {/* input发生变化 获取count */}
      <input type="text" value={count} onChange={(e) => setCount(e.target.value)} />
    </div>
  );
}

useEffect:

useEffect 做了什么? 通过使用这个 Hook,你可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它。在这个 effect 中,我们设置了 document 的 title 属性,不过我们也可以执行数据获取或调用其他命令式的 API。

为什么在组件内部调用 useEffect? 将 useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量(或其他 props)。我们不需要特殊的 API 来读取它 —— 它已经保存在函数作用域中。Hook 使用了 JavaScript 的闭包机制,而不用在 JavaScript 已经提供了解决方案的情况下,还引入特定的 React API。

useEffect 会在每次渲染后都执行吗? 是的,默认情况下,它在第一次渲染之后每次更新之后都会执行。(我们稍后会谈到如何控制它。)你可能会更容易接受 effect 发生在“渲染之后”这种概念,不用再去考虑“挂载”还是“更新”。React 保证了每次运行 effect 的同时,DOM 都已经更新完毕。

useEffect () 本身是一个函数,由 React 框架提供,在函数组件内部调用即可。
useEffect(didUpdate);
useEffect 的使用
import React, { useState, useEffect } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  // useEffect 内的回调函数会在初次渲染后和更新完成后执行
  // 相当于 componentDidMount 和 componentDidUpdate
  useEffect(() => {
    document.title = `您 单击了 ${count} 次`;
  });

  //这里也可以写成
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]); // 仅在 count 更改时更新

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  );
}

useContext :

useContext可以帮助我们跨越组件层级直接传递变量,实现数据共享。
const value = useContext(MyContext);
useContext 的使用

父组件写入

import React,{useEffect,useState,useRef,createRef} from 'react'
import {ThemeContext,ThemeContext2} from './context'
import A3 from './components/A3'

function A2(props) {
  return (
    <div><A3 /></div>
  )
}

//父子传值
function A1(props) {
    const [x1,setX1]=useState('小蓝')

    return (
        <ThemeContext2.Provider value={{title1:x1}}>
            <A2 />
        </ThemeContext2.Provider>
    )
  }

export default function Context(props){
    const [name,setName]=useState("小白");

    const fn=opt=>{
        // console.log(opt,'opt')
    }

    return (
        <ThemeContext.Provider value={{title:'小花'}}>
            <A1
                x2={fn}
            />
        </ThemeContext.Provider>
    )
}

context页面

import React from "react";
// createContext 创建 Context 对象
export const ThemeContext =React.createContext();
export const ThemeContext2 =React.createContext();

子组件 A3页面:

import React,{useContext} from 'react'
import {ThemeContext,ThemeContext2} from '../context'

export default function A3 (props){
    const values=useContext(ThemeContext);
    const values2=useContext(ThemeContext2);

    return (
        <>
            <h2>A1: {values.title}</h2>
            <h2>A3:{values2.title1}</h2>
        </>
    )
}

子组件 Acontext页面

import React,{useContext} from 'react'
import {ThemeContext} from '../context'

export default function Acontext (props){
    const values=useContext(ThemeContext);
    const {xxx}=props
    return (
        <>
            <h1>A3:{xxx}</h1>
            <h2>A3:{values.title}</h2>
        </>
    )
}

useMemo :

useMemo接收两个参数,分别是函数和一个数组(实际上是依赖),函数里return 函数,数组内存放依赖
useMemo的使用:
import React, { useState, useMemo } from 'react';

function counterText({ countInfo }) {
  return (
    <p>{countInfo.name}: {countInfo.number}</p>
  );
}
// // 使用 React.memo 检查 props 变更,复用最近一次渲染结果
const CounterText = React.memo(counterText);

export default function Counter() {
  const [count1, setCount1] = useState(0);
  const [count2, setCount2] = useState(0);

  const countInfo1 = {
    name: 'count1',
    number: count1
  };
  // 使用 useMemo 缓存最近一次计算结果,会在依赖项改变时才重新计算
  const countInfo2 = useMemo(() => ({
    name: 'count2',
    number: count2
  }), [count2]);

  return (
    <>
      <div>
        <CounterText countInfo={countInfo1} />
        <button onClick={() => setCount1(count1 + 1)}>Add count1</button>
      </div>
      <div>
        <CounterText countInfo={countInfo2} />
        <button onClick={() => setCount2(count2 + 1)}>Add count2</button>
      </div>
    </>
  );
}

useCallBack :

是为了缓存方法。我们可以通过自定义hooks函数来使用一下useCallback,我们可以通过自定义hooks函数来实现一个获取窗口大小的函数。
useCallback的使用:
import React, { ReactElement, useCallback, useState } from "react";

const Example = () => {
  const [n, setN] = useState<number>(0);
  const [m, setM] = useState<number>(10);
  console.log("执行最外层盒子了");

  const addN = useCallback(() => {
    setN(n + 1);
  }, [n]);

  const addM = useCallback(() => {
    setM(m + 1);
  }, [m]);
  return (
    <div style={{ textAlign: "center", marginTop: 50 }}>
      最外层盒子
      <Child1 value={n} onClick={addN} />
      <Child2 value={m} onClick={addM} />
      <button onClick={addN}>n+1</button>
      <button onClick={addM}>m+1</button>
    </div>
  );
};

interface childProp {
  value: number;
  onClick?: () => void;
}

const Child1 = React.memo((props: childProp): ReactElement<childProp> => {
  console.log("执行子组件1了");
  return <div>子组件1上的n:{props.value}</div>;
});

const Child2 = React.memo((props: childProp): ReactElement<childProp> => {
  console.log("执行子组件2了");
  return <div>子组件2上的m:{props.value}</div>;
});

export default Example;

useRef:

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。
useRef 的使用:
import React, { useRef } from "react";
export default function App() {
  const r = useRef(0);
  console.log(r);
  const add = () => {
    r.current += 1;
    console.log(`r.current:${r.current}`);
  };
  return (
    <div className="App">
      <h1>r的current:{r.current}</h1>
      <button onClick={add}>点击+1</button>
    </div>
  );
}

useReducer:

使用useReducer接收Reducer函数和一个初始state,并返回当前值state与dispatch函数,并且当触发事件时,使用dispatch传递action,让reducer计算出新的state
可以让你通过 reducer 来管理组件本地的复杂 state。
Reducers 非常便于单独测试,且易于扩展,以表达复杂的更新逻辑。如有必要,您可以将它们分成更小的 reducer。
export default function App() {
  const initialState = { n: 1 };
  const [state, dispatch] = useReducer(reducer, initialState); 
//使用useReducer接收reducer参数和初始state
  return (
    <>
      <div>{state.n}</div>
      <button
        onClick={() => {
          dispatch({ type: "add" });  // 传递action
        }}
      >
        点击+
      </button>
      <button
        onClick={() => {
          dispatch({ type: "sub" });//传递action触发reducer函数
        }}
      >
        点击-
      </button>
    </>
  );
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值