React官方文档:Hook API索引

158 阅读2分钟

useReducer

const [state, dispatch] = userReducer(reducer, initialArg, init)
useState的替代方案。 在某些场景下,useReducer会比useState更适用: 1.state逻辑较复杂且包含多个子值; 2.下一个state依赖于之前的 state; 3.useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。
// 没看懂

const initialState = {count: 0};
function reducer(state, action) {
    switch (action.type) {
        case 'increment':
            return {count: state.count + 1};
        case 'decrement':
            return {count: state.count - 1};
        default:
            throw new Error();
    }
}

function Counter() {
    const [state, dispatch] = useReducer(reducer, initialState);
    return (
        <>
            Count: {state.count}
            <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
        </>
    )
}

如果你想要类似class中的this功能,可以使用一个ref来保存一个可变的变量。

function Example(props) {
    // 把最新的props保存在一个ref中
    const lastestProps = useRef(props)
    useEffect(() => {
        lastestProps.current = props
    });
    useEffect(() => {
        function tick() {
            // 在任何时候读取最新的props
            console.log(lastestProps.current)
        }
        
        const id = setInterval(tick, 1000)
        return () => clearInterval(id)
    }, []); // 这个effect从不会重新执行
}

我该如何实现 shouldComponentUpdate?

useCallback

const memoizedCallback = useCallback(
    () => {
        doSomething(a, b)
    },
    [a, b]
)

返回一个memoized回调函数。 把内联回调函数及依赖项数组作为参数传入useCallback,它将返回该回调函数的memoized版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要(例如shouldCompopnentUpdate)的子组件时,它将非常有用(?) useCallback(fn, deps)相当于useMemo(() => fn, deps)

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])

返回一个memoized值。 把“创建”函数和依赖项数组作为参数传入useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。 如果没有提供依赖项数组,useMemo在每次渲染时都会计算新的值。

useRef

const refContainer = useRef(initialValue);

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

function TextInputWithFocusButton() {
    const inputEl = useRef(null)
    const onButtonClick = () => {
        // `current` 指向已挂载到DOM上的文本输入元素
        inputEl.current.focus();
    }
    return (
        <>
            <input ref={inputEl} type="text" />
            <button onClick={onButtonClick}>Focus the input</button>
        </>
    )
}

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])

useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。 useImperativeHandle应当与forwardRef一起使用:

function FancyInput(props, ref) {
    const inputRef = useRef()
    useImperativeHandle(ref, () => ({
        focus: () => {
            inputRef.current.focus()
        }
    }))
    return <input ref={inputRef} ... />
}
FancyInput = forwardRef(FancyInput)

在本例中,渲染的父组件可以调用inputRef.current.focus()