useState

useState 是一个 React 的 hook ,它的作用是让你向组件添加一个状态变量。

const [state, setState] = useState(initialState);

useState 有两个参数

  1. useState 返回的第一个参数,为我们需要展示或者使用的最新的值
  2. useState 的第二个参数,这个函数是一个 set 函数,可以传入任意变量,让其 state 返回新的值。
function App() {
    const [num, setNum] = useState(1);
    return (
        <div className="App">
            <button onClick={() => setNum(num + 1)}>{num}</button>
        </div>
    );
}

useEffect

useEffect ,是副作用,副作用是指在组件在渲染期间发生的操作,如数据获取,订阅事件,手动操作 dom 等,在函数组件中,由于没有生命周期方法,我们无法再特定的时间执行这些操作,useEffect 正好解决了这个问题

async function getData() {
    return await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(666);
        }, 3000);
    });
}

function App() {
    const [num, setNum] = useState(1);

    useEffect(() => {
        getData().then((data: any) => {
            setNum(data);
        });
    }, []);

    return (
        <div className="App">
            <button onClick={() => setNum((prevNum) => prevNum + 1)}>
                {num}
            </button>
        </div>
    );
}

useLayoutEffect

在 react 中 useLayoutEffect 和 useEffect 是差不都的,在绝大多数情况下,但是事实上是有一定的区别

useEffect 会在渲染内容更新到 dom 上后执行,不会阻塞 dom 的更新 useLayoutEffect 会在渲染更新到 dom 之前就执行,会阻塞 dom 的更新

useReducer

用 useState 是直接修改值,如果想在修改值之前,执行一些操作,可以使用 useReducer

function App() {

  interface Data {
    result: number,
  }

  interface Action {
    type: 'add' | 'minus',
    num: number
  }

  function reducer(state: Data, action: Action) {
    switch (action.type) {
      case 'add':
        return {
          result: state.result + action.num
        }
      case 'minus':
        return {
          result: state.result - action.num
        }
    }
    return state
  }

  const [res, dispatch] = useReducer<Reducer<Data,Action>>(reducer, { result: 0 })

  return (
    <div className="App">
      <button onClick={() => {
        dispatch({ type: 'add', num: 1 })
      }}>{res.result }</button>
    </div>
  );
}

export default App;

useRef

useRef 用来获取 dom 节点,或者获取组件的实例

function App() {
    const inputRef = useRef < HTMLInputElement > null;

    useEffect(() => {
        inputRef.current?.focus();
    }, []);

    return (
        <div className="App">
            <input type="text" ref={inputRef} />
        </div>
    );
}

forwardRef + useImperativeHandle

如果想把子组件的 ref 传递给父组件使用,可以使用 forwardRef 和 useImperativeHandle

比如

import React, { useRef } from "react";
import "./App.css";

const childrenComponent: React.ForwardRefRenderFunction<HTMLInputElement> = (
    props,
    ref
) => {
    return (
        <div>
            <input ref={ref}></input>
        </div>
    );
};

const Wraped = React.forwardRef(childrenComponent);

function App() {
    const ref = useRef < HTMLInputElement > null;

    return (
        <div>
            <Wraped ref={ref} />
        </div>
    );
}

export default App;

切图01

useContext

跨任意组件传递数据,一般都会使用useContext来完成

import React, { createContext, useContext } from 'react';
import './App.css';

const Context = createContext("test")

const Components:React.FC = () => {
  const value = useContext(Context)
 return <div>Context的值是 {value}</div>
}

function App() {
  return <Context.Provider value='222'>
    <div><Components/></div>
  </Context.Provider> 
}

export default App;

切图02

切图03

memo + useMemo + useCallback

memo : 只有组件的props发生变化的时候,才会触发组件的重新渲染,否则总是返回缓存中的结果

useMemo : 一般通过减少不必要的复杂计算来优化性能,类似于计算属性

useCallback : 一般用于给子组件传递回调函数时,减少子组件的渲染次数,从而优化性能。