React Hooks-03 Hook API

useState

const [state, setState] = useState(initialState);
复制代码

seState的函数式更新:如果新的 state 需要通过使用先前的 state 计算得出,那么可以将函数传递给 setState。该函数将接收先前的 state,并返回一个更新后的值

    const [state, setState] = useState(initialState);
    ...
    
    setState(preState => prevState +1);
复制代码

initialState 参数只会在组件的初始渲染中起作用,后续渲染时会被忽略,如果初始 state 需要通过复杂计算获得,则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用

const [state, setState] = useState(()=>{
  const initialState = someExpensiveComputation(props);
  return initialState;
});

复制代码

useEffect

useEffect(didUpdate);
复制代码

该 Hook 接收一个包含命令式、且可能有副作用代码的函数。使用useEffect完成副作用操作。

清除 effect:

赋值给useEffect的函数会在组件渲染到屏幕之后执行,组件卸载时需要清除 effect 创建的诸如订阅或计时器 ID 等资源。要实现这一点,useEffect 函数需返回一个清除函数

    useEffect(()=>{
        const Timer = setInterval(fn,1000);
        return ()=> clearInterval(Timer);
    })
复制代码

执行时机:传给 useEffect的函数会在浏览器完成布局与绘制之后,在一个延迟事件中被调用,在开始新的更新前,React 总会先清除上一轮渲染的 effect。

effect 的条件执行:

默认情况下,effect 会在每轮组件渲染完成后执行,添加第二个参数,控制执行时机

    useEffect(didUpdate,[source]);
复制代码

只有当source变化是,effect才会执行,如果只想运行一次,就传递一个空数组

    useEffect(didUpdate,[]);
复制代码

useContext

const value = useContext(MyContext);
复制代码

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

当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值。即使祖先使用 React.memo 或 shouldComponentUpdate,也会在组件本身使用 useContext 时重新渲染。

useContext(MyContext) 相当于 class 组件中的 static contextType = MyContext 或者 <MyContext.Consumer>。useContext(MyContext) 只是让你能够读取 context 的值以及订阅 context 的变化。你仍然需要在上层组件树中使用 <MyContext.Provider> 来为下层组件提供 context。

useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);
复制代码

useSate 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。(如果你熟悉 Redux 的话,就已经知道它如何工作了。)

在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。

React 会确保 dispatch 函数的标识是稳定的,并且不会在组件重新渲染时改变。这就是为什么可以安全地从 useEffect 或 useCallback 的依赖列表中省略 dispatch。
useCallback

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
复制代码

返回一个 memoized 回调函数。该回调函数仅在某个依赖项改变时才会更新

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。

复制代码

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
复制代码

返回一个 memoized 值。仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。

useRef

const refContainer = useRef(initialValue);
复制代码

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。useRef() 比 ref 属性更有用。它可以很方便地保存任何可变值
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()。

useLayoutEffect

跟useEffect用法相同,不同的在于执行effect时机不同:它会在所有的 DOM 变更之后同步调用 effect(useEffect在DOM变更后延迟执行),可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享