React Hook

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

useState 和 useEffect

useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。
它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并。

将 useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量(或其他 props)。
我们不需要特殊的 API 来读取它 —— 它已经保存在函数作用域中。

案例:

import React, { useState, useEffect } from 'react';

function Hooks () {
    const [ count, setCount ] = useState(0)
    const [ width, setWidth ] = useState(document.body.clientWidth)

    const onChange = () => {
        setWidth(document.body.clientWidth)
    }

    useEffect(() => {
        //相当于 componentDidMount
        window.addEventListener('resize', onChange, false)
        return () => {
            //相当于componentWillUnmount
            window.removeEventListener('resize', onChange, false)
        }
    }, [])

    useEffect(() => {
        //相当于componentDidUpdate
        document.title = count;
    })

    useEffect(() => {
        console.log(`count change: count is ${count}`)
    }, [ count ])

    return (
        <div>
            页面名称: { count }
            页面宽度: { width }
            <button onClick={() => { setCount(count + 1)}}>点我</button>
        </div>
    )
}
// 导出组件
export default Hooks;


useContext

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。
当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。


import React, { useContext } from 'react';

const themes = {
    light: {
      foreground: "#000000",
      background: "#eeeeee",
    },
    dark: {
      foreground: "#ffffff",
      background: "#222222",
      fontSize: "24px"
    }
  };

  const ThemeContext = React.createContext(themes.light);

  function Hook3() {
    return (
      <ThemeContext.Provider value={themes.dark}>
        <Toolbar />
      </ThemeContext.Provider>
    );
  }

  function Toolbar(props) {
    return (
      <div>
        <ThemedButton />
      </div>
    );
  }

  function ThemedButton() {
    const theme = useContext(ThemeContext);
    return (
      <button style={{background: theme.background, color: theme.foreground, fontSize: theme.fontSize }}>
        I am styled by theme context!
      </button>
    );
  }

// 导出组件
export default Hook3;


useReducer

/*
useReducer的作用类似redux中的功能,相较于useState,useReducer适合一些逻辑较复杂且包含多个子值的情况。
reducer接受两个参数,第一个参数是一个reducer,第二个参数是初始 state,返回值为最新的state和dispatch函数。

按照官方的说法,useReducer适合用于复杂的state操作逻辑,嵌套的state的对象的场景。
*/
import React, { useReducer } from 'react';

function Hook3 () {
    const initialState={count:0}
    const [count,dispatch] = useReducer((state,avtion) => {
        switch(avtion.type) {
            case 'add':
                return state+1;
            case 'minus':
                return state-1
            default:
                return state
        }
    },0)
    return (
        <div>
            <div>{count}</div>
            <button onClick={() => {dispatch({type: 'add'})}}>useReducer加</button>
            <button onClick={() => {dispatch({type: 'minus'})}}>useReducer减</button>
        </div>
    )
}
export default Hook3;


useCallback

/*
useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新.
 是来优化子组件的,防止子组件的重复渲染
*/

import React, { useState, useCallback, useEffect } from 'react';

function Parent() {
    const [count, setCount] = useState(1);
    const [val, setVal] = useState('');

    const callback = useCallback(() => {
        return count;
    }, [count]);

    return <div>
        <h4>父组件:{count}</h4>
        <Child callback={callback}/>
        <button onClick={() => setCount(count + 1)}>点我+1</button>
    </div>;
}


function Child({ callback }) {
    const [count, setCount] = useState(() => callback());
    useEffect(() => {
        setCount(callback());
    }, [callback]);
    return <div>
        子组件:{count}
    </div>
}

export default Parent;


useMemo


/*
useMemo: 由于父组件的state发生改变会导致父组件更新,而子组件虽然没有发生改变但是也会进行更新,
优化当前组件主要是通过 memoize 来将一些复杂的计算逻辑进行缓存,其作用类似于类组件的 PureComponent。
会在渲染的时候执行,而不是渲染之后执行,这一点和 useEffect 有区别,所以 useMemo不建议方法中有副作用相关的逻辑
*/ 

import { useMemo , useState} from 'react';

function Hook3 () {
    const [ count, setCount ] = useState(0)
    const add = useMemo(() => {
      return count + 1
    }, [count])
    return (
      <div>
        点击次数: { count }
        <br/>
        次数加一: { add }
        <button onClick={() => { setCount(count + 1)}}>点我</button>
      </div>
      )
  }

export default Hook3;


useRef

/*
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。
返回的 ref 对象在组件的整个生命周期内持续存在。
*/

import React, { useState, useRef } from 'react'

function Hook3(){
    const [count, setCount] = useState(0)
    const counterEl = useRef(null)

    const increment = () => {
        setCount(count + 1)
        console.log(counterEl)
    }

    return (
        <>
            Count: <span ref={counterEl}>{count}</span>
            <button onClick={increment}>Hook3点我+</button>
        </>
    )
}

export default Hook3;
powered by GitbookEdit Time: 2023-04-08 10:28:32