【 React 】Hook 的那些事!

1、Hook 是什么

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

2、Hook 的Api

  • 1、useState 设置类组件中的state
import React, { useState } from "react";
// useState: 可以在函数式组件中声明和修改状态
//函数式组件
function App() {
	//使用hook来定义state
	//获得state,和修改state的函数。
    const [value, setValue] = useState("123");
    如果初始值比较复杂,可以用一个函数包裹,返回一个复杂对象。
    const [userInfo, setUserInfo] = useState(getUserInfo);
    //如果需要定义多个状态,就调用多次useState
    return (
        <div>
            <p>value: {value}</p>
            <input type="text" value={value} onChange={onChangeAction} />  
            <input type="text" value={value} onChange={onChangeAction()} />  
            // 这里加不加括号结果 都是一样的。应该在内部做了判断吧。

        </div>
    )
    // 输入框的修改事件
    const onChangeAction = (ev) => {
    	//调用上面定义的修改函数,要返回一个新的state,保证state的属性是不可变量。
        setValue(ev.target.value);
    };
    const getUserInfo = ()=>{
    	return {
    		a:1,
    		b:2
    		}
    	}
}
export default App
  • 2、useEffect 用来模拟 类组件中的各种生命周期钩子函数
//解构出`effect` // useEffect: 需要有一组依赖的state,如果依赖的state发生变化, 那么回调就会执行。
import React, { useState, useEffect } from "react";
... //下面是函数组件内部代码
const [value, setValue] = useState("123");
// effect

// 只要组件的所有state/props发生变化就执行。以及初始化也会执行
useEffect(()=>{
    console.log('1  useEffect run.......');
});

// 如果第二个参数提供了数组,数组中只能是state的值或者props的值
// 只有依赖发生变化,回来哦函数才执行。并且判断是否发生变化,比较的是状态的引用。
useEffect(()=>{
    console.log('2  useEffect run.......');
}, [value, props.data]);

// 如果第二个参数为空数组,那么第一个回调就相当于class组件的componentDidMount
useEffect(()=>{
    console.log('3  useEffect run.......');
    //而且在effect函数中是可以拿到DOM对象的
}, []);

useEffect(()=>{
    console.log('4  useEffect run.......');
    console.log(document.querySelector('#flag').innerHTML);
    // 返回的函数,会在下一次渲染完组件后,执行下一次的useEffect前,先调用上一次返回的useEffect返回的函数。
    return (...rest)=>{
      console.log('4  useEffect return func run.......');
      console.log(document.querySelector('#flag').innerHTML);
}
});

useEffect(()=>{
    console.log('5  useEffect run.......');
    return ()=>{
      // 当依赖为空时,useEffect返回的函数,相当于class组件的componentWillUnmount
      console.log('5  useEffect return func run.......');
}
}, []);

//暂时Hook 只能模拟这几个钩子函数
  • 3、useRef 用来拿到DOM对象,类组件中的 React.createRef 一样。
import React, {  useRef } from 'react'

... //下面是函数组件内部代码
let h4DOM = useRef();
return (
	//用法和类组件中一样,都是从current中取值。
      <h4 ref={h4DOM}>test</h4>
//    console.log(h4DOM.current);
)
  • 4、useContext 提供数据的用法和类组件是一样的,不同点在于消费数据。
//初始化仓库数据,可以用useState,同时提供数据和修改数据的方法。
  const [value, setValue] = useState(1)
        <DataContext.Provider
        value={{
          value,
          setValue,
          //将属性和修改属性的方法,一起存在仓库中
        }}
      >
        <div className="app">
          <One />
          <hr />
          <Two />
        </div>
      </DataContext.Provider>

//调用的时候
import React, {useContext} from 'react'
import DataContext from '../context/DataContext'
import ThemeContext from '../context/ThemeContext'

export default function Two() {
  const context = useContext(DataContext);
  console.log(context);

  const context2 = useContext(ThemeContext);
  console.log(context2);

  return (
    <div>
      <h1>{context.value}</h1>
      <button onClick={()=>{
        context.setValue(context.value+1);
        }}>修改</button>
    </div>
  )
}

  • 5、useCallback 该hook,保证了某一些特殊函数,只执行一次,避免过多执行而消耗性能,第一个参数是想只执行一次的函数体,第二个参数可以是函数体用到的依赖状态。
import React, { useEffect, useState, useCallback } from 'react'


const list = [];

export default function App() {
  console.log('render.....');

  const [value, setValue] = useState('');

  // useCallback作用:声明一次函数,当组件再次渲染,取上次渲染时声明的函数直接使用。
  // 但是,当依赖发生变化时,又会重新声明一次函数。
  // 如果在组件中定义局部的函数,那么就是用useCallback包裹,注意useCallback的依赖一定要正确。
  const valueChange = useCallback((ev)=>{
    console.log(value);
    setValue(ev.target.value);
  }, [value]);

  useEffect(()=>{
    list.push(valueChange);
    console.log(list.length);
    if(list.length === 2){
      console.log(list[0] === list[1]);
    }
  });
  return (
    <div className="app">
      <h1>value: {value}</h1>
      <input type="text" value={value} onChange={valueChange}/>
    </div>
  )

}
  • 6、useMemo 相当于计算属性,只有依赖的值发生变化,才会执行memo包裹的函数。
import React, { useState, useCallback, useMemo, memo } from "react";

function One() {
    console.log("render............");
    const [a, setA] = useState(1);
    const [b, setB] = useState(2);
    const [c, setC] = useState(3);

    const list = [];
    // useMemo相当于计算属性
    // 第一个参数是个函数,需要返回计算的属性,第二个参数是依赖,依赖发生变化,重新计算属性。
    const result = useMemo(() => {
        // 计算属性的代码
        var result = 100;
        for (var i = 1; i <= a && i <= b; i++) {
            console.log("计算最大公约数...");
            if (a % i === 0 && b % i === 0) {
                result = i;
            }
        }
        // 计算得到的属性,需要返回出去
        return result;
    }, [a, b]);

    console.log(result);

    const btn1Action = useCallback(() => {
        setA((a) => a + 1);
    }, []);

    const btn2Action = useCallback(() => {
        setB((b) => b + 1);
    }, []);

    const btn3Action = useCallback(() => {
        setC((c) => c + 1);
    }, []);

    return (
        <div>
            <p>A: {a}</p>
            <p>b: {b}</p>
            <p>AB的最大公约数:{result}</p>
            <p>c: {c}</p>
            <button onClick={btn1Action}>修改A</button>
            <button onClick={btn2Action}>修改B</button>
            <button onClick={btn3Action}>修改C</button>
        </div>
    );
}

export default memo(One);

  • 7、useHistory 与 useLocation 与 useMatch 用来获取路由参数,相当于类组件中的 withRouter 高阶组件。
import React from "react";
import { useHistory, useLocation ,useRouteMatch ,useParams } from "react-router-dom";
//在类组件中除了 利用 component 属性来跳转的路由,其他都拿不到上面三个属性,需要用到高阶组件 withRouter包裹才能用到。
//利用Hook 就可以直接拿到。但是要是在Router的包裹范围内。
export default function Two(props) {
  const history = useHistory();
  console.log(history);
  const location = useLocation();
  console.log(location);
}
  • 8 、useSelect 与 useDispatch 与 useStore 用来获取store中的数据和方法。类组件中用到高阶组件 content
import React from 'react'
import { useCallback } from 'react';
import {useSelector, useDispatch, useStore} from 'react-redux'


export default function One(props) {

  // 获取redux仓库中的数据
  const val = useSelector(state=>{
    return state.value;
  });

  // 获取dispatch
  const dispatch = useDispatch();

  const btnAction = useCallback(()=>{
    dispatch({type: 'modify-value', value: 'hello'});
  }, [dispatch]);

  // 获得仓库
  const store = useStore();
  console.log(store);

  return (
    <div className="one">
      <h1>one组件</h1>

      <h2>{val}</h2>

      <button onClick={btnAction}>修改value</button>
      
    </div>
  )
}


©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页