Hooks API及useState、useEffect手动封装

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

一、Hooks API

Hooks API分为基础Hook额外的Hook

基础Hooke

1. useState

usestate的使用:useState 的使用非常简单,我们从 React 中拿到 useState 后,只需要在使用的地方直接调用 useState 函数就可以, useState 会返回一个数组,第一个值是我们的 state第二个值是一个函数,用来修改该 state 的,那么这里为什么叫 count 和 setCount?一定要叫这个吗,这里使用了 es6 的解构赋值,所以你可以给它起任何名字:如updateCount, doCount、any thing,当然,为了编码规范,所以建议统一使用一种命名规范,尤其是第二个值

2. useEffect

Effect Hook 可以让你在函数组件中执行副作用操作,这里提到副作用,什么是副作用呢,就是除了状态相关的逻辑,比如网络请求,监听事件,查找 dom

3. useContext

useContext:context 中的 Provider 和 Consumer,在类组件和函数组件中都能使用,contextType 只能在类组件中使用,因为它是类的静态属性

额外的Hooke

1. useReducer

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

2. useCallback

useCallback 是什么呢,可以说是 useMemo 的语法糖,能用 useCallback 实现的,都可以使用 useMemo, 在 react 中我们经常面临一个子组件渲染优化的问题, 尤其是在向子组件传递函数props时,每次 render 都会创建新函数,导致子组件不必要的渲染,浪费性能,这个时候,就是 useCallback 的用武之地了,useCallback 可以保证,无论 render 多少次,我们的函数都是同一个函数,减小不断创建的开销。 同样,useCallback 的第二个参数和useMemo一样,没有区别

3. useMemo

useMemo 是什么呢,它跟 memo 有关系吗 ,说白了 memo 就是函数组件的 PureComponent,用来做性能优化的手段,useMemo 也是,useMemo 在我的印象中和 Vue 的 computed 计算属性类似,都是根据依赖的值计算出结果,当依赖的值未发生改变的时候,不触发状态改变

4. useRef

useRef 有什么作用呢,其实很简单,总共有两种用法

  1. 获取子组件的实例(只有类组件可用)
  2. 在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx

获取子组件实例

5. useImperativeHandle

useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值,说简单点就是,子组件可以选择性的暴露给副组件一些方法,这样可以隐藏一些私有方法和属性

6. useLayoutEffect

其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。

7. useDebugValue

useDebugValue 接受一个格式化函数作为可选的第二个参数。该函数只有在 Hook 被检查时才会被调用。它接受 debug 值作为参数,并且会返回一个格式化的显示值。

二、useState的手动封装

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.1/umd/react.development.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.1/umd/react-dom.development.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
</head>

<body>


    <div id="root"></div>
    <script type="text/babel">
        console.log(ReactDOM);

        let initState = []
        let initIndex = 0
        function cutUserState(state) {
            let currentIndex = initIndex
            initState[currentIndex] = initState[currentIndex] ? initState[currentIndex] : state
            function changeState(newState) {
                initState[currentIndex] = newState
                initIndex=0
                render()

            }
            initIndex++
            return [initState[currentIndex], changeState]
        }


        function App() {
            const [count, setCount] = cutUserState(0)
            console.log(count);
            return (
                <div>
                    <p>{count}</p>
                    <button onClick={() => {
                        setCount(count + 1)
                    }}>+++</button>
                </div>
            )
        }

        function render() {
            ReactDOM.render(
                <App />,
                document.getElementById('root')
            )
        }
        render()
    </script>

</body>

</html>
复制代码

三、useEffect的手动封装

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.1/umd/react.development.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.1/umd/react-dom.development.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
</head>

<body>


    <div id="root"></div>
    <script type="text/babel">
       
      function cutUseEffect(callback,deps){
         let oldState=initState[initIndex]
         let isChange=oldState?[...new Set([...oldState,...deps])].length!==deps.length:false
   if(!deps||ischange){
    callback()
   }
   initState[initIndex]=deps
}
      function App(){
        const [count,setCount]=cutUserState(0)
        cutUseEffect(()=>{
        console.log('effect count')
    },[count])
       return (
        <div>
         <p>{count}</p> 
      <button onclick={()=>{setCount(count+1)}}>+++</button>         
 </div>
   )
   }
        function render() {
            ReactDOM.render(
                <App />,
                document.getElementById('root')
            )
        }
        render()
    </script>

</body>

</html>


 }
复制代码

image.png

おすすめ

転載: juejin.im/post/7050418733365329934